diff --git a/src/app/router/Router.tsx b/src/app/router/Router.tsx index 1c33d0bd..c0c79df7 100644 --- a/src/app/router/Router.tsx +++ b/src/app/router/Router.tsx @@ -7,6 +7,7 @@ import { AroundSearch, TourList, TourSearch, + TourSingleInfo, } from '@/app/router'; import { Home } from '@/pages/home'; import { GeoTrip } from '@/pages/tour/geotrip'; @@ -28,6 +29,7 @@ export default function Router() { }> } /> + } /> } /> } /> } /> diff --git a/src/app/router/lazyRoutes.ts b/src/app/router/lazyRoutes.ts index b5a9a24c..d20ea25e 100644 --- a/src/app/router/lazyRoutes.ts +++ b/src/app/router/lazyRoutes.ts @@ -9,3 +9,6 @@ export const AroundSearch = lazy( ); export const TourList = lazy(() => import('@/pages/tour/tourList/TourList')); export const TourSearch = lazy(() => import('@/pages/tour/search/TourSearch')); +export const TourSingleInfo = lazy( + () => import('@/pages/tour/geotrip/SingleTrip'), +); diff --git a/src/features/shared/lib/useKakaoShare.ts b/src/features/shared/lib/useKakaoShare.ts new file mode 100644 index 00000000..a6ca6282 --- /dev/null +++ b/src/features/shared/lib/useKakaoShare.ts @@ -0,0 +1,70 @@ +import { tourQueries } from '@/entities/tour'; +import { useQuery } from '@tanstack/react-query'; +import { useEffect } from 'react'; + +declare global { + interface Window { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Kakao: any; + } +} + +interface UseKakaoShareParams { + contentId: string; + link: string; +} + +const useKakaoShare = ({ contentId, link }: UseKakaoShareParams) => { + const { data } = useQuery({ + ...tourQueries.detailCommon(contentId), + }); + + useEffect(() => { + // SDK 로드 + const script = document.createElement('script'); + script.src = 'https://t1.kakaocdn.net/kakao_js_sdk/2.7.0/kakao.min.js'; + script.async = true; + document.body.appendChild(script); + + return () => { + document.body.removeChild(script); + }; + }, []); + + const shareKakao = () => { + if (window.Kakao) { + const kakao = window.Kakao; + if (!kakao.isInitialized()) { + kakao.init(import.meta.env.VITE_KAKAO_MAP_KEY); + } + window.Kakao.Share.sendDefault({ + objectType: 'feed', + content: { + title: data?.title ?? '여행지 추천', + description: data?.overview ?? '멋진 여행지를 확인해보세요!', + imageUrl: + data?.firstimage || + data?.firstimage2 || + 'https://developers.kakao.com/assets/img/about/logos/kakaolink/kakaolink_btn_medium.png', + link: { + mobileWebUrl: link, + webUrl: link, + }, + }, + buttons: [ + { + title: '여행 시작하기', + link: { + mobileWebUrl: link, + webUrl: link, + }, + }, + ], + }); + } + }; + + return { shareKakao }; +}; + +export default useKakaoShare; diff --git a/src/features/shared/ui/SharedButtonContainer.tsx b/src/features/shared/ui/SharedButtonContainer.tsx new file mode 100644 index 00000000..23d3998a --- /dev/null +++ b/src/features/shared/ui/SharedButtonContainer.tsx @@ -0,0 +1,25 @@ +/* eslint-disable */ +import { commonSVG } from '@/assets'; +import useKakaoShare from '../lib/useKakaoShare'; + +interface SharedButtonContainerProps { + contentId: string; +} + +export default function SharedButtonContainer({ + contentId, +}: SharedButtonContainerProps) { + const link = `${window.location.origin}/tour/single/${contentId}`; + + const { shareKakao } = useKakaoShare({ contentId, link }); + return ( + + ); +} diff --git a/src/features/tour/ui/single/Single.tsx b/src/features/tour/ui/single/Single.tsx new file mode 100644 index 00000000..373a0e74 --- /dev/null +++ b/src/features/tour/ui/single/Single.tsx @@ -0,0 +1,38 @@ +import { useNavigate, useParams } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; + +import { tourQueries, type TourItem } from '@/entities/tour'; +import { LoadingSpinner } from '@/shared/ui'; +import { TourSlide } from '@/features/tourShort'; + +export default function Single() { + const { contentId } = useParams(); + const navigate = useNavigate(); + + const { data: tourInfo, isLoading } = useQuery({ + ...tourQueries.detailCommon(contentId!), + enabled: !!contentId, + }); + + // 로딩 중일 때 + if (isLoading) { + return ( +
+ +
+ ); + } + + const handleRedirectMainPage = () => { + navigate('/tour/geo-trip?distance=20000&tour-type=12'); + }; + + return ( +
+ +
+ ); +} diff --git a/src/features/tourList/ui/TourInfoCard.tsx b/src/features/tourList/ui/TourInfoCard.tsx index b02804f8..219b2611 100644 --- a/src/features/tourList/ui/TourInfoCard.tsx +++ b/src/features/tourList/ui/TourInfoCard.tsx @@ -1,5 +1,4 @@ import { Suspense } from 'react'; -import { commonSVG } from '@/assets'; import { TourCardImages } from '@/features/tourList'; import { SkeletonCard, StartTripButton } from '@/features/tour'; @@ -13,6 +12,7 @@ import { } from '@/shared'; import type { TourItem } from '@/entities/tour'; +import SharedButtonContainer from '@/features/shared/ui/SharedButtonContainer'; interface TourInfoCardProps { tourInfo: TourItem; } @@ -40,9 +40,7 @@ export default function TourInfoCard({ tourInfo }: TourInfoCardProps) {