Skip to content

Commit

Permalink
Feat: 검색 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
ssumai-kr committed Jul 15, 2024
1 parent 93ace9d commit 6ff208a
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 37 deletions.
40 changes: 31 additions & 9 deletions components/CatergoryBtn/CatergoryBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
import { useState } from 'react';
import { CategoryBtnProps } from './CategoryBtn.types';
import { useRecoilState, useRecoilValue } from 'recoil';
import { mainPageKategorieState, mainPageState } from '@/states/mainPageState';

export default function CatergoryBtn({ categoryName }: CategoryBtnProps) {
const [isActive, setIsActive] = useState(false);
export default function CatergoryBtn({
categoryName,
}: CategoryBtnProps) {
const [selectedKategorie, setSelectedKategorie] = useRecoilState(
mainPageKategorieState
);
const [currentPage, setCurrentPage] = useRecoilState(mainPageState);

const { KategorieName } = useRecoilValue(mainPageKategorieState);

const handleClick = () => {
setIsActive(!isActive);
if (categoryName === KategorieName) {
setSelectedKategorie({ KategorieName: '' });
setCurrentPage((prev) => ({
...prev,
currentPage: 1,
}))
} else {
setSelectedKategorie({ KategorieName: categoryName });
setCurrentPage((prev) => ({
...prev,
currentPage: 1,
}))
}
};

const isSelected = categoryName === KategorieName;
const backgroundColor = isSelected ? 'bg-black' : 'bg-white';
const textColor = isSelected ? 'text-white' : 'text-black';

return (
<button
className={`flex items-center justify-center rounded-[15px] border-[1px] border-solid border-var-green2 w-[127px] h-[53px] t:min-w-[120px] m:min-w-[80px] m:h-[41px] ${isActive ? 'bg-nomad-black' : 'bg-white'}`}
className={`flex items-center justify-center rounded-[15px] border-[1px] border-solid border-var-green2 w-[127px] h-[53px] t:min-w-[120px] m:min-w-[80px] m:h-[41px] ${backgroundColor}`}
onClick={handleClick}
>
<p
className={`text-[18px] m:text-[14px] ${isActive ? 'text-white' : 'text-var-green2'}`}
>
{categoryName}
</p>
<p className={`text-[18px] m:text-[14px] ${textColor}`}>{categoryName}</p>
</button>
);
}
26 changes: 14 additions & 12 deletions components/Lander/AllActivities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import Pagination from '../Pagination/Pagination';
import { useRecoilState, useRecoilValue } from 'recoil';
import { mainPageState } from '@/states/mainPageState';
import { mainPageKategorieState, mainPageState } from '@/states/mainPageState';
import Spinner from '../Spinner/Spinner';

const Kategories = ['문화 · 예술', '식음료', '스포츠', '투어', '관광', '웰빙'];

function AllActivity({
export function AllActivity({
title,
backgroundImage,
price,
Expand Down Expand Up @@ -68,10 +68,6 @@ function AllActivity({
}

function AllActivities() {
const router = useRouter();
// const [currentPage, setCurrentPage] = useState<number>(
// router.query.page ? parseInt(router.query.page as string, 10) : 1
// );
const [MainPageState, setMainPageState] = useRecoilState(mainPageState);

const {
Expand All @@ -80,6 +76,8 @@ function AllActivities() {
currentPage,
} = useRecoilValue(mainPageState);

const { KategorieName } = useRecoilValue(mainPageKategorieState);

const setItemsPerPage = () => {
if (typeof window !== 'undefined') {
// 브라우저 환경에서만 실행
Expand All @@ -97,14 +95,15 @@ function AllActivities() {
setMainPageState((prevState) => ({
...prevState,
itemsPerPage,
currentPage: 1,
}));
}
};

const params: getActivityListParams = {
method: 'offset',
cursorId: null,
category: null,
category: KategorieName,
keyword: null,
sort: selectedSorted,
page: currentPage,
Expand All @@ -121,12 +120,10 @@ function AllActivities() {
});

const handlePageChange = (page: number) => {
//setCurrentPage(page);
setMainPageState((prevState) => ({
...prevState,
currentPage: page,
}));
//router.push(`/?page=${page}`);
};

useEffect(() => {
Expand All @@ -145,7 +142,7 @@ function AllActivities() {
const params: getActivityListParams = {
method: 'offset',
cursorId: null,
category: null,
category: KategorieName,
keyword: null,
sort: selectedSorted,
page: currentPage,
Expand All @@ -155,7 +152,7 @@ function AllActivities() {

return (
<div>
<div className="flex justify-between mb-[38px]">
<div className="flex justify-between">
<div className="relative t:w-[520px] m:w-[230px]">
<div className="flex gap-[24px] t:gap-[14px] m:gap-[8px] t:w-[520px] m:w-[230px] overflow-auto scrollbar-hide">
{Kategories.map((Kategorie, index) => (
Expand All @@ -166,8 +163,13 @@ function AllActivities() {
</div>
<PriceFilterBtn />
</div>
<div className="font-sans text-[36px] font-[700] mt-[40px] mb-[30px]">
{KategorieName ? KategorieName : '🛼 모든 체험'}
</div>
{isLoading ? (
<Spinner />
<div className='mt-[-300px]'>
<Spinner />
</div>
) : (
<div className="grid grid-cols-4 t:grid-cols-3 m:grid-cols-2 grid-rows-2 gap-[20px] t:gap-[14px] m:gap-[6px] gap-y-[48px] mb-[40px] overflow-auto scrollbar-hide">
{allActivitiesData?.activities.map((data) => (
Expand Down
28 changes: 19 additions & 9 deletions components/Lander/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Image from 'next/image';
import Testimgae from './TestImage.jpg';
import SearchBar from '../SearchBar/Searchbar';
import BestActivities from './BestActivities';
import AllActivities from './AllActivities';
Expand All @@ -10,8 +8,14 @@ import {
} from '@/pages/api/activities/apiactivities.types';
import { getActivityList } from '@/pages/api/activities/apiactivities';
import Spinner from '../Spinner/Spinner';
import { useState } from 'react';
import SearchResults from './SearchResults';
import { useRecoilValue } from 'recoil';
import { mainSearchValueState } from '@/states/mainPageState';

function Main() {
const [isSearch, setIsSearch] = useState(false);
const {SearchValue} = useRecoilValue(mainSearchValueState);
const date = new Date();
const month = date.getMonth() + 1;
//const {id, title, bannerImageUrl} = useRecoilValue(BestOfmonth);
Expand Down Expand Up @@ -56,14 +60,20 @@ function Main() {
</span>
</div>
<div className="mt-[120px] m:mt-[14px] flex justify-center">
<SearchBar></SearchBar>
</div>
<div className="mt-[40px]">
<BestActivities></BestActivities>
</div>
<div className=" mt-[60px]">
<AllActivities></AllActivities>
<SearchBar setIsSearch={setIsSearch}></SearchBar>
</div>
{isSearch ? (
<SearchResults SearchValue={SearchValue} />
) : (
<div>
<div className="mt-[40px]">
<BestActivities></BestActivities>
</div>
<div className=" mt-[60px]">
<AllActivities></AllActivities>
</div>
</div>
)}
</div>
</main>
);
Expand Down
10 changes: 10 additions & 0 deletions components/Lander/Main.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ export interface mainPageStateProps {
selectedSorted: string;
sortedName: string;
}

export interface mainPageKategorieStateProps {
KategorieName: string;
}

export interface mainSearchValueStateProps {
SearchValue: string;
currentPage: number;
itemsPerPage: number;
}
134 changes: 134 additions & 0 deletions components/Lander/SearchResults.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { useRecoilState, useRecoilValue } from 'recoil';
import { SearchResultsProps } from './SearchResults.type';
import { mainSearchValueState } from '@/states/mainPageState';
import { useEffect } from 'react';
import {
getActivityListParams,
getActivityListResponse,
} from '@/pages/api/activities/apiactivities.types';
import { useQuery } from '@tanstack/react-query';
import { getActivityList } from '@/pages/api/activities/apiactivities';
import { AllActivity } from './AllActivities';
import Pagination from '../Pagination/Pagination';
import Spinner from '../Spinner/Spinner';

function SearchResults({ SearchValue }: SearchResultsProps) {
const [searchresultsState, setSearchResultsState] =
useRecoilState(mainSearchValueState);

const {
SearchValue: resultsValue,
currentPage,
itemsPerPage,
} = useRecoilValue(mainSearchValueState);

const setItemsPerPage = () => {
if (typeof window !== 'undefined') {
// 브라우저 환경에서만 실행
const width = window.innerWidth;

let itemsPerPage;
if (width >= 1281) {
itemsPerPage = 16;
} else if (width > 744) {
itemsPerPage = 9;
} else {
itemsPerPage = 6;
}

setSearchResultsState((prevState) => ({
...prevState,
itemsPerPage,
currentPage: 1,
}));
}
};
useEffect(() => {
setItemsPerPage();
if (typeof window !== 'undefined') {
window.addEventListener('resize', setItemsPerPage);
}
return () => {
if (typeof window !== 'undefined') {
window.removeEventListener('resize', setItemsPerPage);
}
};
}, []);

useEffect(() => {
setSearchResultsState((prevState) => ({
...prevState,
SearchValue,
}));
}, [SearchValue, setSearchResultsState]);

const params: getActivityListParams = {
method: 'offset',
cursorId: null,
category: null,
keyword: resultsValue,
sort: '',
page: currentPage,
size: itemsPerPage,
};

const {
data: SearchResultsData,
error,
isLoading,
} = useQuery<getActivityListResponse>({
queryKey: ['AllActivities', params],
queryFn: () => getActivityList(params),
});

const handlePageChange = (page: number) => {
setSearchResultsState((prevState) => ({
...prevState,
currentPage: page,
}));
};

return (
<div className="mt-[40px]">
<div className="font-sans text-[32px] font-[400] mb-[12px]">
"
<span className="font-sans text-[32px] font-[700]">{resultsValue}</span>
"으로 검색한 결과입니다.
</div>
<div className="font-sans text-[16px] font-[400] mb-[24px]">
{SearchResultsData?.totalCount}개의 결과
</div>
{isLoading ? (
<div className="mt-[-300px]">
<Spinner />
</div>
) : (
<div className="grid grid-cols-4 t:grid-cols-3 m:grid-cols-2 grid-rows-2 gap-[20px] t:gap-[14px] m:gap-[6px] gap-y-[48px] mb-[40px] overflow-auto scrollbar-hide">
{SearchResultsData?.activities.map((data) => (
<AllActivity
key={data.id}
title={data.title}
backgroundImage={data.bannerImageUrl}
price={data.price}
rating={data.rating}
reviewCount={data.reviewCount}
id={data.id}
/>
))}
</div>
)}
<div className="text-[30px] font-[700] flex justify-center mb-[342px] mt-[70px]">
{SearchResultsData && SearchResultsData.totalCount > 0 && (
<Pagination
totalItems={SearchResultsData?.totalCount}
itemsPerPage={itemsPerPage}
currentPage={currentPage}
onPageChange={handlePageChange}
/>
)}
</div>
</div>
);
}

export default SearchResults;
Empty file.
Loading

0 comments on commit 6ff208a

Please sign in to comment.