From 327a8e85cc173e1aae90333136154000ba6687e5 Mon Sep 17 00:00:00 2001 From: joanShim Date: Wed, 17 Jan 2024 23:15:47 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Feat:=20=EC=9A=B0=EB=A6=AC=EC=9D=98=20?= =?UTF-8?q?=EA=B4=80=EC=8B=AC=EB=AA=A9=EB=A1=9D=20=EC=B6=94=EA=B0=80=20=20?= =?UTF-8?q?1=EC=B0=A8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=ED=8E=98=EC=B9=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/button/ListSelectBtn.tsx | 57 +++++++++++ src/pages/plan/OurLikedList.tsx | 97 +++++++++++++++++++ src/pages/plan/addPlace/MyLiked.tsx | 80 +++++++++++++++ src/pages/plan/addPlace/MyLikedList.tsx | 62 ++++++++++++ src/pages/plan/addPlace/MyLikedListItem.tsx | 57 +++++++++++ src/pages/plan/addPlace/PlanAddPlace.page.tsx | 32 ++++++ .../plan/addPlace/ResultCategoryPlan.tsx | 45 +++++++++ src/pages/plan/addPlace/ResultItem.tsx | 33 +++++++ src/pages/plan/addPlace/SearchResult.tsx | 94 ++++++++++++++++++ src/pages/plan/planPlaceTrip.page.tsx | 5 - src/pages/trip/AddOurList.tsx | 32 ++++++ src/recoil/listItem.ts | 6 ++ src/router/socketRouter.tsx | 6 +- 13 files changed, 599 insertions(+), 7 deletions(-) create mode 100644 src/components/common/button/ListSelectBtn.tsx create mode 100644 src/pages/plan/OurLikedList.tsx create mode 100644 src/pages/plan/addPlace/MyLiked.tsx create mode 100644 src/pages/plan/addPlace/MyLikedList.tsx create mode 100644 src/pages/plan/addPlace/MyLikedListItem.tsx create mode 100644 src/pages/plan/addPlace/PlanAddPlace.page.tsx create mode 100644 src/pages/plan/addPlace/ResultCategoryPlan.tsx create mode 100644 src/pages/plan/addPlace/ResultItem.tsx create mode 100644 src/pages/plan/addPlace/SearchResult.tsx delete mode 100644 src/pages/plan/planPlaceTrip.page.tsx create mode 100644 src/pages/trip/AddOurList.tsx create mode 100644 src/recoil/listItem.ts diff --git a/src/components/common/button/ListSelectBtn.tsx b/src/components/common/button/ListSelectBtn.tsx new file mode 100644 index 00000000..4328e6d2 --- /dev/null +++ b/src/components/common/button/ListSelectBtn.tsx @@ -0,0 +1,57 @@ +import { useState, ReactNode } from 'react'; +import { CheckIcon } from '../icons/Icons'; + +interface ListSelectBtnProps { + children: ReactNode; + onClick?: () => void; +} + +export const ListSelectBtn = ({ children, onClick }: ListSelectBtnProps) => { + const [isActive, setIsActive] = useState(false); + + const handleClick = () => { + setIsActive(!isActive); + if (onClick) { + onClick(); + } + }; + + return ( + + ); +}; + +interface ListCheckBtnProps { + onClick?: () => void; +} + +export const ListCheckBtn = ({ onClick }: ListCheckBtnProps) => { + const [isActive, setIsActive] = useState(false); + + const handleClick = () => { + setIsActive(!isActive); + if (onClick) { + onClick(); + } + }; + + return ( +
+ +
+ ); +}; diff --git a/src/pages/plan/OurLikedList.tsx b/src/pages/plan/OurLikedList.tsx new file mode 100644 index 00000000..86fc475f --- /dev/null +++ b/src/pages/plan/OurLikedList.tsx @@ -0,0 +1,97 @@ +import { useInfiniteQuery } from '@tanstack/react-query'; +import ToursCategoryItem from '@components/Tours/ToursCategoryItem'; +import { useEffect, useState } from 'react'; +import { Spinner } from '@components/common/spinner/Spinner'; +import { getMemberTours } from '@api/member'; +import WishList from '@components/Wish/WishList'; + +export const OurLikedList = () => { + const categories = ['전체', '숙소', '식당', '관광지']; + + const [selectedContentTypeId, setSelectedContentTypeId] = useState< + null | number + >(null); + + const [selectedCategory, setSelectedCategory] = useState('전체'); + useEffect(() => { + console.log(selectedCategory); + }, [selectedCategory]); + + const handleSelectCategory = (category: string) => { + setSelectedCategory(category); + }; + + // useEffect(() => { + // console.log('searchWord: ' + searchWord); + // }, [searchWord]); + // console.log(); + + const { fetchNextPage, hasNextPage, data, isLoading, isError } = + useInfiniteQuery({ + queryKey: ['wishList'], + queryFn: ({ pageParam = 0 }) => getMemberTours(pageParam, 10), + initialPageParam: 0, + getNextPageParam: (lastPage) => { + if ( + lastPage && + lastPage.data && + lastPage.data && + lastPage.data.pageable + ) { + const currentPage = lastPage.data.pageable.pageNumber; + const totalPages = lastPage.data.totalPages; + + if (currentPage < totalPages - 1) { + return currentPage + 1; + } + } + return undefined; + }, + }); + + const handleCategoryClick = (contentTypeId: number | null) => { + setSelectedContentTypeId(contentTypeId); + }; + + if (isLoading) { + return ; + } + if (isError) { + console.log('error fetching search result '); + } + + // console.log(data?.pages[0].data.content); + const searchResults = data?.pages.flatMap((page) => page.data.content) || []; + console.log('searchResults', searchResults); + const noResults = searchResults && searchResults.length === 0; + + return ( + <> +
우리의 관심 목록
+
+ {categories.map((category) => ( + + ))} +
+ {noResults ? ( +
+ 나의 관심목록이 없습니다. +
+ ) : ( +
+ // + )} + + ); +}; diff --git a/src/pages/plan/addPlace/MyLiked.tsx b/src/pages/plan/addPlace/MyLiked.tsx new file mode 100644 index 00000000..ea917e60 --- /dev/null +++ b/src/pages/plan/addPlace/MyLiked.tsx @@ -0,0 +1,80 @@ +import { useInfiniteQuery } from '@tanstack/react-query'; +import { useState } from 'react'; +import { Spinner } from '@components/common/spinner/Spinner'; +import { getMemberTours } from '@api/member'; +import { MyLikedList } from './MyLikedList'; +import { ButtonPrimary } from '@components/common/button/Button'; +import WishCategory from '@components/Wish/WishCategory'; + +export const MyLiked = () => { + const [selectedContentTypeId, setSelectedContentTypeId] = useState< + null | number + >(null); + + // const [selectedCategory, setSelectedCategory] = useState('전체'); + // useEffect(() => { + // console.log(selectedCategory); + // }, [selectedCategory]); + + const handleCategoryClick = (contentTypeId: number | null) => { + setSelectedContentTypeId(contentTypeId); + }; + + const { fetchNextPage, hasNextPage, data, isLoading, isError } = + useInfiniteQuery({ + queryKey: ['wishList'], + queryFn: ({ pageParam = 0 }) => getMemberTours(pageParam, 10), + initialPageParam: 0, + getNextPageParam: (lastPage) => { + if ( + lastPage && + lastPage.data && + lastPage.data && + lastPage.data.pageable + ) { + const currentPage = lastPage.data.pageable.pageNumber; + const totalPages = lastPage.data.totalPages; + + if (currentPage < totalPages - 1) { + return currentPage + 1; + } + } + return undefined; + }, + }); + + if (isLoading) { + return ; + } + if (isError) { + console.log('error fetching search result '); + } + + // console.log(data?.pages[0].data.content); + const searchResults = data?.pages.flatMap((page) => page.data.content) || []; + console.log('searchResults', searchResults); + const noResults = searchResults && searchResults.length === 0; + + return ( + <> +
나의 관심 목록
+ + {noResults ? ( +
+ 나의 관심목록이 없습니다. +
+ ) : ( + + )} +
+ 추가하기 +
+ + ); +}; diff --git a/src/pages/plan/addPlace/MyLikedList.tsx b/src/pages/plan/addPlace/MyLikedList.tsx new file mode 100644 index 00000000..295328c6 --- /dev/null +++ b/src/pages/plan/addPlace/MyLikedList.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import InfiniteScroll from 'react-infinite-scroller'; +import { v4 as uuidv4 } from 'uuid'; +import { MyLikedListItem } from './MyLikedListItem'; +import { TourType } from '@/@types/tours.types'; +import { Spinner } from '@components/common/spinner/Spinner'; + +interface WishListProps { + toursData: { pages: Array<{ data: { content: TourType[] } }> }; + fetchNextPage: () => void; + hasNextPage: boolean; + isLoading: boolean; + selectedContentTypeId: number | null; +} + +export const MyLikedList: React.FC = ({ + toursData, + fetchNextPage, + hasNextPage, + isLoading, + selectedContentTypeId, +}) => { + if (!toursData || toursData.pages.length === 0) { + return
데이터를 불러오는 중 오류가 발생했습니다.
; + } + + const filteredData = + selectedContentTypeId !== null + ? toursData.pages.map((group) => ({ + data: { + content: group.data.content.filter( + (item) => item.contentTypeId === selectedContentTypeId, + ), + }, + })) + : toursData.pages; + + return ( +
+ fetchNextPage()} + hasMore={hasNextPage} + loader={ +
+ +
+ }> +
+ {!isLoading && + filteredData.map((group) => ( + + {group?.data.content.map((wishList: TourType) => ( + + ))} + + ))} +
+
+
+ ); +}; diff --git a/src/pages/plan/addPlace/MyLikedListItem.tsx b/src/pages/plan/addPlace/MyLikedListItem.tsx new file mode 100644 index 00000000..c1cdcfa7 --- /dev/null +++ b/src/pages/plan/addPlace/MyLikedListItem.tsx @@ -0,0 +1,57 @@ +import { TourType } from '@/@types/tours.types'; +import { ListCheckBtn } from '@components/common/button/ListSelectBtn'; +import { StarIcon } from '@components/common/icons/Icons'; +import { selectedItemsState } from '@recoil/listItem'; +import { useRecoilState } from 'recoil'; + +interface WishItemProps { + wishList: TourType; +} + +export const MyLikedListItem: React.FC = ({ wishList }) => { + const { + id, + title, + ratingAverage, + reviewCount, + smallThumbnailUrl, + tourAddress, + } = wishList; + + const [selectedItems, setSelectedItems] = useRecoilState(selectedItemsState); + + const handleSelect = () => { + if (selectedItems.includes(id)) { + setSelectedItems(selectedItems.filter((item) => item !== id)); + } else { + setSelectedItems([...selectedItems, id]); + } + }; + + return ( +
+
+ {title} +
+
+
{title}
+
+
+ +
+ + {ratingAverage}({reviewCount}) + + + {tourAddress} + +
+
+ +
+ ); +}; diff --git a/src/pages/plan/addPlace/PlanAddPlace.page.tsx b/src/pages/plan/addPlace/PlanAddPlace.page.tsx new file mode 100644 index 00000000..98002a06 --- /dev/null +++ b/src/pages/plan/addPlace/PlanAddPlace.page.tsx @@ -0,0 +1,32 @@ +import SearchInput from '@components/search/SearchInput'; +import { useEffect, useState } from 'react'; +import { useLocation } from 'react-router-dom'; +import { SearchResultForPlan } from './SearchResult'; +import { OurLikedList } from '../OurLikedList'; + +export const PlanAddPlace = () => { + const location = useLocation(); + + const queryParams = new URLSearchParams(location.search); + const searchWordFromQuery = queryParams.get('searchWord'); + + const [searchWord, setSearchWord] = useState(''); + + useEffect(() => { + if (searchWordFromQuery) { + setSearchWord(searchWordFromQuery); + } else { + setSearchWord(''); + } + }, [location, searchWordFromQuery]); + return ( + <> + + {searchWord ? ( + + ) : ( + + )} + + ); +}; diff --git a/src/pages/plan/addPlace/ResultCategoryPlan.tsx b/src/pages/plan/addPlace/ResultCategoryPlan.tsx new file mode 100644 index 00000000..294c29bd --- /dev/null +++ b/src/pages/plan/addPlace/ResultCategoryPlan.tsx @@ -0,0 +1,45 @@ +import { ButtonPrimary, ButtonWhite } from '@components/common/button/Button'; +import { TourType } from '@/@types/tours.types'; +import { InfiniteQueryObserverResult } from '@tanstack/react-query'; +import { ResultItemPlan } from './ResultItem'; + +interface ResultCategoryProps { + data: TourType[]; + category: string; + fetchNextPage: (() => Promise>) | null; + hasNextPage: boolean; + isFetchingNextPage: boolean; +} + +export const ResultCategoryPlan = ({ + data, + fetchNextPage, + hasNextPage, + isFetchingNextPage, +}: ResultCategoryProps) => { + // console.log('hasNextPage', hasNextPage); + return ( + <> +

ResultCategoryPlan

+ {data.map((item) => ( + + ))} + {hasNextPage && !isFetchingNextPage ? ( + fetchNextPage && fetchNextPage()}> + 더보기 + + ) : isFetchingNextPage ? ( + + Loading... + + ) : ( +
+ )} +
+ 추가하기 +
+ + ); +}; diff --git a/src/pages/plan/addPlace/ResultItem.tsx b/src/pages/plan/addPlace/ResultItem.tsx new file mode 100644 index 00000000..cb2849aa --- /dev/null +++ b/src/pages/plan/addPlace/ResultItem.tsx @@ -0,0 +1,33 @@ +import { TourType } from '@/@types/tours.types'; +import { ListSelectBtn } from '@components/common/button/ListSelectBtn'; +import { StarIcon } from '@components/common/icons/Icons'; + +export const ResultItemPlan = ({ result }: { result: TourType }) => { + console.log(result); + return ( +
+
+ {result.title} +
+
+
{result.title}
+
+
+ +
+ + {result.ratingAverage}({result.reviewCount}) + + + {result.tourAddress} + +
+
+ 선택 +
+ ); +}; diff --git a/src/pages/plan/addPlace/SearchResult.tsx b/src/pages/plan/addPlace/SearchResult.tsx new file mode 100644 index 00000000..485f37e8 --- /dev/null +++ b/src/pages/plan/addPlace/SearchResult.tsx @@ -0,0 +1,94 @@ +import { getToursSearch } from '@api/tours'; +import { useInfiniteQuery } from '@tanstack/react-query'; +import ToursCategoryItem from '@components/Tours/ToursCategoryItem'; +import { useEffect, useState } from 'react'; +import { Spinner } from '@components/common/spinner/Spinner'; +import { ResultCategoryPlan } from './ResultCategoryPlan'; + +interface SearchResultProps { + searchWord: string; +} + +export const SearchResultForPlan = ({ searchWord }: SearchResultProps) => { + const categories = ['전체', '숙소', '식당', '관광지']; + const [selectedCategory, setSelectedCategory] = useState('전체'); + useEffect(() => { + console.log(selectedCategory); + }, [selectedCategory]); + + const handleSelectCategory = (category: string) => { + setSelectedCategory(category); + }; + + useEffect(() => { + console.log('searchWord: ' + searchWord); + }, [searchWord]); + console.log(); + + const { + data, + fetchNextPage, + hasNextPage, + isLoading, + isError, + isFetchingNextPage, + } = useInfiniteQuery({ + queryKey: ['searchResults', searchWord, selectedCategory], + queryFn: ({ pageParam = 0 }) => + getToursSearch({ + region: '', + searchWord: searchWord, + category: selectedCategory !== '전체' ? selectedCategory : undefined, + page: pageParam, + size: 20, + }), + initialPageParam: 0, + getNextPageParam: (lastPage, allPages) => { + if (!lastPage.data.data.last) { + return allPages.length; + } + return undefined; + }, + enabled: !!searchWord, + retry: 2, + }); + + if (isLoading) { + return ; + } + if (isError) { + console.log('error fetching search result '); + } + + const searchResults = + data?.pages.flatMap((page) => page.data.data.content) || []; + console.log('searchResults', searchResults); + const noResults = searchResults && searchResults.length === 0; + + return ( + <> +
+ {categories.map((category) => ( + + ))} +
+ + {noResults ? ( +
검색결과가 없습니다.
+ ) : ( + + )} + + ); +}; diff --git a/src/pages/plan/planPlaceTrip.page.tsx b/src/pages/plan/planPlaceTrip.page.tsx deleted file mode 100644 index 4ff978c4..00000000 --- a/src/pages/plan/planPlaceTrip.page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const PlanPlaceTrip = () => { - return
여행계획 - 장소 추가 페이지
; -}; - -export default PlanPlaceTrip; diff --git a/src/pages/trip/AddOurList.tsx b/src/pages/trip/AddOurList.tsx new file mode 100644 index 00000000..80bce838 --- /dev/null +++ b/src/pages/trip/AddOurList.tsx @@ -0,0 +1,32 @@ +import SearchInput from '@components/search/SearchInput'; +import { MyLiked } from '@pages/plan/addPlace/MyLiked'; +import { SearchResultForPlan } from '@pages/plan/addPlace/SearchResult'; +import { useEffect, useState } from 'react'; +import { useLocation } from 'react-router-dom'; + +export const AddOurList = () => { + const location = useLocation(); + + const queryParams = new URLSearchParams(location.search); + const searchWordFromQuery = queryParams.get('searchWord'); + + const [searchWord, setSearchWord] = useState(''); + + useEffect(() => { + if (searchWordFromQuery) { + setSearchWord(searchWordFromQuery); + } else { + setSearchWord(''); + } + }, [location, searchWordFromQuery]); + return ( +
+ + {searchWord ? ( + + ) : ( + + )} +
+ ); +}; diff --git a/src/recoil/listItem.ts b/src/recoil/listItem.ts new file mode 100644 index 00000000..72eb7456 --- /dev/null +++ b/src/recoil/listItem.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const selectedItemsState = atom({ + key: 'selectedItemsState', + default: [], +}); diff --git a/src/router/socketRouter.tsx b/src/router/socketRouter.tsx index 0d3b67d9..80faf2db 100644 --- a/src/router/socketRouter.tsx +++ b/src/router/socketRouter.tsx @@ -1,12 +1,13 @@ import { Route, Routes } from 'react-router-dom'; import { useSocket, socketContext } from '@hooks/useSocket'; import PlanTrip from '@pages/plan/planTrip.page'; -import PlanPlaceTrip from '@pages/plan/planPlaceTrip.page'; +import { PlanAddPlace } from '@pages/plan/addPlace/PlanAddPlace.page'; import PlanPlaceSearch from '@pages/plan/planPlaceSearch.page'; import Trip from '@pages/trip/trip.page'; import MainLayout from './routerLayout'; import { useRecoilValue } from 'recoil'; import { tripIdState, visitDateState } from '@recoil/socket'; +import { AddOurList } from '@pages/trip/AddOurList'; const SocketRoutes = () => { const tripId = useRecoilValue(tripIdState); @@ -20,7 +21,7 @@ const SocketRoutes = () => { } /> - } /> + } /> } /> @@ -32,6 +33,7 @@ const SocketRouter = () => { }> } /> + } /> } /> From 87c5f3d948c3bb00d163289028a50c31a8b25465 Mon Sep 17 00:00:00 2001 From: joanShim Date: Thu, 18 Jan 2024 01:03:32 +0900 Subject: [PATCH 2/2] =?UTF-8?q?Feat:=20=EC=9A=B0=EB=A6=AC=EC=9D=98=20?= =?UTF-8?q?=EA=B4=80=EC=8B=AC=EB=AA=A9=EB=A1=9D=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/trips.ts | 8 ++- src/pages/plan/OurLikedList.tsx | 57 ++++++++++--------- src/pages/plan/addPlace/AddtoListBtn.tsx | 36 ++++++++++++ src/pages/plan/addPlace/MyLiked.tsx | 11 +--- .../plan/addPlace/ResultCategoryPlan.tsx | 8 ++- src/pages/plan/addPlace/ResultItem.tsx | 14 ++++- 6 files changed, 92 insertions(+), 42 deletions(-) create mode 100644 src/pages/plan/addPlace/AddtoListBtn.tsx diff --git a/src/api/trips.ts b/src/api/trips.ts index 3441cb6b..84d5ed51 100644 --- a/src/api/trips.ts +++ b/src/api/trips.ts @@ -47,7 +47,13 @@ export const getTripsLike = async ( // 우리의 관심 목록 등록 export const postTripsLike = async (tripId: number, tourItemIds: number[]) => { - const res = await client.post(`trips/${tripId}/tripLikedTours`, tourItemIds); + const requestBody = { + tourItemIds: tourItemIds, + }; + const res = await authClient.post( + `trips/${tripId}/tripLikedTours`, + requestBody, + ); return res; }; diff --git a/src/pages/plan/OurLikedList.tsx b/src/pages/plan/OurLikedList.tsx index 86fc475f..bb192296 100644 --- a/src/pages/plan/OurLikedList.tsx +++ b/src/pages/plan/OurLikedList.tsx @@ -3,14 +3,13 @@ import ToursCategoryItem from '@components/Tours/ToursCategoryItem'; import { useEffect, useState } from 'react'; import { Spinner } from '@components/common/spinner/Spinner'; import { getMemberTours } from '@api/member'; -import WishList from '@components/Wish/WishList'; export const OurLikedList = () => { const categories = ['전체', '숙소', '식당', '관광지']; - const [selectedContentTypeId, setSelectedContentTypeId] = useState< - null | number - >(null); + // const [selectedContentTypeId, setSelectedContentTypeId] = useState< + // null | number + // >(null); const [selectedCategory, setSelectedCategory] = useState('전체'); useEffect(() => { @@ -26,32 +25,36 @@ export const OurLikedList = () => { // }, [searchWord]); // console.log(); - const { fetchNextPage, hasNextPage, data, isLoading, isError } = - useInfiniteQuery({ - queryKey: ['wishList'], - queryFn: ({ pageParam = 0 }) => getMemberTours(pageParam, 10), - initialPageParam: 0, - getNextPageParam: (lastPage) => { - if ( - lastPage && - lastPage.data && - lastPage.data && - lastPage.data.pageable - ) { - const currentPage = lastPage.data.pageable.pageNumber; - const totalPages = lastPage.data.totalPages; + const { + // fetchNextPage, hasNextPage, + data, + isLoading, + isError, + } = useInfiniteQuery({ + queryKey: ['wishList'], + queryFn: ({ pageParam = 0 }) => getMemberTours(pageParam, 10), + initialPageParam: 0, + getNextPageParam: (lastPage) => { + if ( + lastPage && + lastPage.data && + lastPage.data && + lastPage.data.pageable + ) { + const currentPage = lastPage.data.pageable.pageNumber; + const totalPages = lastPage.data.totalPages; - if (currentPage < totalPages - 1) { - return currentPage + 1; - } + if (currentPage < totalPages - 1) { + return currentPage + 1; } - return undefined; - }, - }); + } + return undefined; + }, + }); - const handleCategoryClick = (contentTypeId: number | null) => { - setSelectedContentTypeId(contentTypeId); - }; + // const handleCategoryClick = (contentTypeId: number | null) => { + // setSelectedContentTypeId(contentTypeId); + // }; if (isLoading) { return ; diff --git a/src/pages/plan/addPlace/AddtoListBtn.tsx b/src/pages/plan/addPlace/AddtoListBtn.tsx new file mode 100644 index 00000000..9e54f742 --- /dev/null +++ b/src/pages/plan/addPlace/AddtoListBtn.tsx @@ -0,0 +1,36 @@ +import { useRecoilValue } from 'recoil'; +import { selectedItemsState } from '@recoil/listItem'; +import { ButtonPrimary } from '@components/common/button/Button'; +import { postTripsLike } from '@api/trips'; +// import { useNavigate } from 'react-router-dom'; + +const AddToListButton = () => { + const selectedTourItemIds = useRecoilValue(selectedItemsState); + // const navigate = useNavigate(); + + const getTripIdFromUrl = () => { + const pathSegments = window.location.pathname.split('/'); + const tripIdIndex = + pathSegments.findIndex((segment) => segment === 'trip') + 1; + return pathSegments[tripIdIndex] + ? parseInt(pathSegments[tripIdIndex], 10) + : null; + }; + + const handleAddClick = async () => { + const tripId = getTripIdFromUrl(); + if (tripId) { + try { + const response = await postTripsLike(tripId, selectedTourItemIds); + console.log('API response:', response); + // navigate(`/trip/${tripId}`); + } catch (error) { + console.error('API error:', error); + } + } + }; + + return 추가하기; +}; + +export default AddToListButton; diff --git a/src/pages/plan/addPlace/MyLiked.tsx b/src/pages/plan/addPlace/MyLiked.tsx index ea917e60..5e65a8d3 100644 --- a/src/pages/plan/addPlace/MyLiked.tsx +++ b/src/pages/plan/addPlace/MyLiked.tsx @@ -3,19 +3,14 @@ import { useState } from 'react'; import { Spinner } from '@components/common/spinner/Spinner'; import { getMemberTours } from '@api/member'; import { MyLikedList } from './MyLikedList'; -import { ButtonPrimary } from '@components/common/button/Button'; import WishCategory from '@components/Wish/WishCategory'; +import AddToListButton from './AddtoListBtn'; export const MyLiked = () => { const [selectedContentTypeId, setSelectedContentTypeId] = useState< null | number >(null); - // const [selectedCategory, setSelectedCategory] = useState('전체'); - // useEffect(() => { - // console.log(selectedCategory); - // }, [selectedCategory]); - const handleCategoryClick = (contentTypeId: number | null) => { setSelectedContentTypeId(contentTypeId); }; @@ -50,9 +45,7 @@ export const MyLiked = () => { console.log('error fetching search result '); } - // console.log(data?.pages[0].data.content); const searchResults = data?.pages.flatMap((page) => page.data.content) || []; - console.log('searchResults', searchResults); const noResults = searchResults && searchResults.length === 0; return ( @@ -73,7 +66,7 @@ export const MyLiked = () => { /> )}
- 추가하기 +
); diff --git a/src/pages/plan/addPlace/ResultCategoryPlan.tsx b/src/pages/plan/addPlace/ResultCategoryPlan.tsx index 294c29bd..7e3f8706 100644 --- a/src/pages/plan/addPlace/ResultCategoryPlan.tsx +++ b/src/pages/plan/addPlace/ResultCategoryPlan.tsx @@ -1,7 +1,8 @@ -import { ButtonPrimary, ButtonWhite } from '@components/common/button/Button'; +import { ButtonWhite } from '@components/common/button/Button'; import { TourType } from '@/@types/tours.types'; import { InfiniteQueryObserverResult } from '@tanstack/react-query'; import { ResultItemPlan } from './ResultItem'; +import AddToListButton from './AddtoListBtn'; interface ResultCategoryProps { data: TourType[]; @@ -17,7 +18,6 @@ export const ResultCategoryPlan = ({ hasNextPage, isFetchingNextPage, }: ResultCategoryProps) => { - // console.log('hasNextPage', hasNextPage); return ( <>

ResultCategoryPlan

@@ -38,7 +38,9 @@ export const ResultCategoryPlan = ({
)}
- 추가하기 +
+ +
); diff --git a/src/pages/plan/addPlace/ResultItem.tsx b/src/pages/plan/addPlace/ResultItem.tsx index cb2849aa..9ad70dde 100644 --- a/src/pages/plan/addPlace/ResultItem.tsx +++ b/src/pages/plan/addPlace/ResultItem.tsx @@ -1,9 +1,19 @@ import { TourType } from '@/@types/tours.types'; import { ListSelectBtn } from '@components/common/button/ListSelectBtn'; import { StarIcon } from '@components/common/icons/Icons'; +import { selectedItemsState } from '@recoil/listItem'; +import { useRecoilState } from 'recoil'; export const ResultItemPlan = ({ result }: { result: TourType }) => { - console.log(result); + const [selectedItems, setSelectedItems] = useRecoilState(selectedItemsState); + const id = result.id; + const handleSelect = () => { + if (selectedItems.includes(id)) { + setSelectedItems(selectedItems.filter((item) => item !== id)); + } else { + setSelectedItems([...selectedItems, id]); + } + }; return (
@@ -27,7 +37,7 @@ export const ResultItemPlan = ({ result }: { result: TourType }) => {
- 선택 + 선택 ); };