Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

220 feat trip connect search #230

Merged
merged 4 commits into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions src/api/detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export const getIsWish = async (id: number) => {
const response = await axios.get(`/api/wishes/${id}`, {
withCredentials: true,
});
const data: boolean = response.data;
return data;
const data = response.data;
return data.data;
} catch (error) {
if (axios.isAxiosError(error)) {
console.log(error);
Expand Down
77 changes: 43 additions & 34 deletions src/api/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,77 @@ import {Dispatch} from 'react';

import {translateCategoryCode, translateLocation, translateSort} from '@/utils/translateSearchData';

import {DataType, Keywords, Popular, Search, SearchHotItemType, SearchItemType, SearchKeywordType} from '@/types/home';
import {DataType, Keywords, Popular, Search, SearchHotItemType, SearchKeywordType} from '@/types/home';

export async function search(
keyword: string,
location: string,
sort: string,
set: Dispatch<React.SetStateAction<SearchItemType[] | undefined>>,
) {
interface PramsType {
keyword?: string;
page: number;
size: number;
sort: string;
categoryCode?: string;
areaCode?: number;
sigunguCode?: number;
}

export async function search(keyword: string, location: string, sort: string, page: number) {
try {
const searchLocation = translateLocation(location);
const params: PramsType = {
keyword: keyword,
page: page,
size: 20,
sort: translateSort(sort),
};
if (searchLocation.areaCode !== 0) {
params.areaCode = searchLocation.areaCode;
if (searchLocation.sigunguCode !== 0) {
params.sigunguCode = searchLocation.sigunguCode;
}
}
const fetchData = await axios.get('/api/places/search', {
params: {
page: 0,
size: 20,
areaCode: searchLocation.areaCode,
sigunguCode: searchLocation.sigunguCode,
keyword: keyword,
sort: translateSort(sort),
},
params: params,
});
const data: DataType<Search> = fetchData.data;
console.log(data.data.places);
set(data?.data.places);
return data?.data.places;
} catch (error) {
console.log(error);
}
}

export async function keywordSearch(
keyword: string,
location: string,
sort: string,
set: Dispatch<React.SetStateAction<SearchItemType[] | undefined>>,
) {
export async function keywordSearch(keyword: string, location: string, sort: string, page: number, size = 20) {
try {
const searchLocation = translateLocation(location);
const categoryCode = translateCategoryCode(keyword);
const params: PramsType = {
page: page,
size: size,
sort: translateSort(sort),
categoryCode: categoryCode,
};
if (searchLocation.areaCode !== 0) {
params.areaCode = searchLocation.areaCode;
if (searchLocation.sigunguCode !== 0) {
params.sigunguCode = searchLocation.sigunguCode;
}
}

const fetchData = await axios.get('/api/places/search', {
params: {
page: 0,
size: 20,
areaCode: searchLocation.areaCode,
sigunguCode: searchLocation.sigunguCode,
sort: translateSort(sort),
categoryCode: categoryCode,
},
params: params,
});
const data: DataType<Search> = fetchData.data;

set(data?.data.places);
return data?.data.places;
} catch (error) {
console.log(error);
}
}

export async function getPopularItem(
apiURL: string,
type: number,
set: Dispatch<React.SetStateAction<SearchHotItemType[] | undefined>>,
) {
try {
const fetchData = await axios.get(`${apiURL}`, {
const fetchData = await axios.get('/api/places/popular', {
params: {
size: 10,
placeTypeId: type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import {BiTask} from 'react-icons/bi';
import {CiEdit} from 'react-icons/ci';
import {FaRegHeart} from 'react-icons/fa';
import {IoShareSocialOutline} from 'react-icons/io5';
import {useLocation} from 'react-router-dom';
import {useRecoilState, useSetRecoilState} from 'recoil';

import styles from './MeatballBottomSlide.module.scss';

import {useDeleteWishes, usePostWishes} from '@/hooks/Detail/useWish';

import CustomToast from '@/components/CustomToast/CustomToast';

import CloseIcon from '@/assets/close.svg?react';
Expand All @@ -16,8 +19,6 @@ import RegistrationSlide from '../../BottomFixedBtn/RegistrationSlide/Registrati
import ReviewBottomSlide from '../../Contents/ReviewBottomSlide/ReviewBottomSlide';

import {NavigationMeatballProps} from '@/types/detail';
import {useDeleteWishes, usePostWishes} from '@/hooks/Detail/useWish';
import {useLocation} from 'react-router-dom';

const MeatballBottomSlide = ({onBottomSlideOpen, onClose, id, contentTypeId, title}: NavigationMeatballProps) => {
const [isWish, setIsWish] = useRecoilState(IsHeartValued);
Expand All @@ -41,8 +42,8 @@ const MeatballBottomSlide = ({onBottomSlideOpen, onClose, id, contentTypeId, tit
};
const showToast = CustomToast();

const postWishes = usePostWishes();
const deleteWishes = useDeleteWishes();
const postWishes = usePostWishes(id);
const deleteWishes = useDeleteWishes(id);

const handleHeartClick = () => {
if (isLogin) {
Expand Down
20 changes: 10 additions & 10 deletions src/components/Home/RecommendedItemList/RecommendedItemList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,6 @@ function RecommendedItemList({apiNum}: PropsType) {
},
],
[
{
id: 3065360,
contentTypeId: 28,
title: '부산 요트투어 요트야',
thumbnail: 'https://d2ur7st6jjikze.cloudfront.net/offer_photos/119386/832573_large_1686709791.jpg?1686709791',
areaCode: 6,
sigunguCode: 16,
category: '관광',
rating: '5.0',
},
{
id: 2774550,
contentTypeId: 28,
Expand Down Expand Up @@ -229,6 +219,16 @@ function RecommendedItemList({apiNum}: PropsType) {
category: '관광',
rating: '4.5',
},
{
id: 3065360,
contentTypeId: 28,
title: '부산 요트투어 요트야',
thumbnail: 'https://d2ur7st6jjikze.cloudfront.net/offer_photos/119386/832573_large_1686709791.jpg?1686709791',
areaCode: 6,
sigunguCode: 16,
category: '관광',
rating: '5.0',
},
],
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function CardHaveVote({data}: PropsType) {
<span>{data.title}</span>
</p>
</div>
<Link to={`/votes/${data.voteId}`} className={styles.button_box}>
<Link to={`trip/${data.spaceInfo.spaceId}/votes/${data.voteId}`} className={styles.button_box}>
<button>
투표하기
<p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function HotItems({type}: PropsType) {
const [componentRef, size] = useComponentSize();

useEffect(() => {
getPopularItem('/api/places/popular', type, setData);
getPopularItem(type, setData);
}, [type]);
return (
<div className={styles.container}>
Expand Down
77 changes: 65 additions & 12 deletions src/components/SearchFromHome/SearchList/SearchList.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import {InfiniteData, useInfiniteQuery} from '@tanstack/react-query';
import {useEffect, useState} from 'react';
import {useInView} from 'react-intersection-observer';
import {useNavigate} from 'react-router-dom';

import styles from './SearchList.module.scss';

import AddToCandidateButton from '@/components/ButtonsInAddingCandidate/AddToCandidateButton/AddToCandidateButton';
import ObserveTarget from '@/components/Route/ObserveTarget/ObserveTarget';

import {keywordSearch, search} from '@/api/search';
import SearchNull from '@/assets/homeIcons/search/searchNull.svg?react';
Expand All @@ -22,34 +25,81 @@ interface PropsType {
}

function SearchList({forSearch}: PropsType) {
const [data, setData] = useState<SearchItemType[] | undefined>();
const [filterData, setFilterData] = useState<SearchItemType[] | undefined>();
const [isEnd, setIsEnd] = useState(false);
const [categoryChange, setCategoryChange] = useState(false);
const {ref: inViewRef, inView} = useInView({
rootMargin: '100px 0px 0px 0px',
threshold: 1,
});
const navigate = useNavigate();

useEffect(() => {
async function getData(page: number) {
if (forSearch.hot === 'true') {
keywordSearch(forSearch.keyword, forSearch.location, forSearch.sort, setData);
const fetchData = await keywordSearch(forSearch.keyword, forSearch.location, forSearch.sort, page + 1);
if (fetchData?.length === 0) {
setIsEnd(true);
return [];
}
return fetchData;
} else {
search(forSearch.keyword, forSearch.location, forSearch.sort, setData);
const fetchData = await search(forSearch.keyword, forSearch.location, forSearch.sort, page + 1);
if (fetchData?.length === 0) {
setIsEnd(true);
return [];
}
return fetchData;
}
}

const {data, fetchNextPage} = useInfiniteQuery<unknown, Error, InfiniteData<SearchItemType[], unknown>>({
queryKey: [`${forSearch.keyword} ${forSearch.location} ${forSearch.sort} ${forSearch.hot}`],
queryFn: ({pageParam = 0}) => getData(pageParam as number),
initialPageParam: 0,
refetchOnWindowFocus: false,
getNextPageParam: (pageParam, allPage) => {
if (!allPage) {
return pageParam;
}
return allPage.length;
},
});

useEffect(() => {
if (!isEnd && inView) {
console.log(1);

fetchNextPage();
}
}, [forSearch.keyword, forSearch.location, forSearch.sort, forSearch.hot]);
}, [inView]);

useEffect(() => {
console.log(data);

if (data) {
if (forSearch.category !== 0) {
let filterData;
const filterData: SearchItemType[][] = [];
if (forSearch.category === 14) {
filterData = data.filter((data) => data.contentTypeId === 14 || data.contentTypeId === 15);
data.pages.map((data) => {
const filter = data.filter((data) => data.contentTypeId === 14 || data.contentTypeId === 15);
filterData.push(filter);
});
} else {
filterData = data.filter((data) => data.contentTypeId === forSearch.category);
data.pages.map((data) => {
const filter = data.filter((data) => data.contentTypeId === forSearch.category);
filterData.push(filter);
});
}
setFilterData(filterData);
setFilterData(filterData.flat());
} else {
setFilterData(data);
setFilterData(data.pages.flat());
}
}
}, [data, forSearch.category]);
}, [forSearch.category, data]);

useEffect(() => {
setIsEnd(false);
}, [forSearch.location, forSearch.sort]);

function onMap() {
navigate(
Expand All @@ -65,7 +115,9 @@ function SearchList({forSearch}: PropsType) {
paddingTop: forSearch.placeID !== 'undefinde' ? '24px' : 0,
}}
>
{forSearch.hot === 'false' && <Tabs data={data} forSearch={forSearch} setCategoryChange={setCategoryChange} />}
{forSearch.hot === 'false' && (
<Tabs data={data?.pages.flat()} forSearch={forSearch} setCategoryChange={setCategoryChange} />
)}
{forSearch.map === 'true' && filterData ? (
<Map data={filterData} categoryChange={categoryChange} />
) : (
Expand All @@ -85,6 +137,7 @@ function SearchList({forSearch}: PropsType) {
<span>검색 결과가 없습니다.</span>
</div>
)}
{filterData && filterData?.length > 0 && !isEnd && <ObserveTarget inViewRef={inViewRef} />}
</ul>
{forSearch.placeID !== 'undefined' ? (
<AddToCandidateButton />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ const AddCandidate = () => {
<VoteSearchIcon />
<p>장소 검색</p>
</button>
<button className={styles.container__buttons__item}>
<button
className={styles.container__buttons__item}
onClick={() => {
navigate(`/wishes/bring?category=0&location=전국&sort=등록순&placeID=${spaceId}&tripDate=vote ${voteId}`);
}}
>
<VoteHeartIcon />
<p>찜 목록 검색</p>
</button>
Expand Down
Loading
Loading