diff --git a/src/apis/workplace.ts b/src/apis/workplace.ts index 604cd1e..d770d25 100644 --- a/src/apis/workplace.ts +++ b/src/apis/workplace.ts @@ -144,6 +144,14 @@ export const postPositionWorkPlace = async ({ return response.data; }; +// 하이브리드 필터링 사업장 조회 +export const getRecommendWorkPlace = async (): Promise< + GetPositionWorkPlaceData[] +> => { + const response = await authInstance.post('/api/v1/recommend'); + return response.data; +}; + // 사업자 사업장 조회 export const getBusinessWorkPlace = async (): Promise => { diff --git a/src/pages/MainPage/components/KakaoMap.tsx b/src/pages/MainPage/components/KakaoMap.tsx index b01bc9d..ed111e2 100644 --- a/src/pages/MainPage/components/KakaoMap.tsx +++ b/src/pages/MainPage/components/KakaoMap.tsx @@ -7,10 +7,12 @@ import PlaceModal from './PlaceModal'; interface KakaoMapProps { data: GetPositionWorkPlaceData[] | undefined; + activeTab: string; + recommendData: GetPositionWorkPlaceData[]; } const KakaoMap = (props: KakaoMapProps) => { - const { data } = props; + const { data, activeTab, recommendData } = props; const { mapPosition, @@ -88,7 +90,8 @@ const KakaoMap = (props: KakaoMapProps) => { setCenterPosition({ lat: latlng.getLat(), lng: latlng.getLng() }); }} > - {data && + {activeTab === '주변 스터디룸' && + data && data.length > 0 && data.map((item) => ( { }} /> ))} + {activeTab === '맞춤형 추천' && + recommendData && + recommendData.length > 0 && + recommendData.map((item) => ( + handleMarkerClick(item)} + key={item.positionLat} + position={{ lat: item.positionLat, lng: item.positionLon }} + image={{ + src: 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png', + size: { + width: 24, + height: 35, + }, + }} + /> + ))}
@@ -58,6 +89,28 @@ const MainList = (props: MainListProps) => { studyroom={item} /> ))} + {activeTab === '맞춤형 추천' && !isLogin && ( +
+ 로그인 후 이용이 가능합니다. + +
+ )} + {activeTab === '맞춤형 추천' && + !isRecommendLoading && + recommendData && + recommendData.length > 0 && + recommendData.map((item) => ( + + ))} {(!isLoading || isError) && activeTab === '주변 스터디룸' && (!data || data.length === 0) && ( @@ -65,11 +118,14 @@ const MainList = (props: MainListProps) => { 주변 스터디룸이 없습니다.
)} - {activeTab === '맞춤형 추천' && ( -
- 추천 스터디룸이 없습니다. -
- )} + {(!isRecommendLoading || isRecommendError) && + (!recommendData || recommendData.length === 0) && + isLogin && + activeTab === '맞춤형 추천' && ( +
+ 추천 스터디룸이 없습니다. +
+ )} ); diff --git a/src/pages/MainPage/components/StudyRoomCard.tsx b/src/pages/MainPage/components/StudyRoomCard.tsx index 130c1da..7be3f6f 100644 --- a/src/pages/MainPage/components/StudyRoomCard.tsx +++ b/src/pages/MainPage/components/StudyRoomCard.tsx @@ -35,7 +35,11 @@ const StudyRoomCard = ({ studyroom }: StudyRoomCardProps) => {

{workplaceName}

- {distance.toFixed(2)}km + {distance && ( + + {distance.toFixed(2)}km + + )} {formattedAddress}
diff --git a/src/pages/MainPage/hooks/useGetWorkplaceData.tsx b/src/pages/MainPage/hooks/useGetWorkplaceData.tsx index c6e30c7..8878c25 100644 --- a/src/pages/MainPage/hooks/useGetWorkplaceData.tsx +++ b/src/pages/MainPage/hooks/useGetWorkplaceData.tsx @@ -1,4 +1,4 @@ -import { postPositionWorkPlace } from '@apis/workplace'; +import { getRecommendWorkPlace, postPositionWorkPlace } from '@apis/workplace'; import { useQuery } from '@tanstack/react-query'; import { GetPositionWorkPlaceData, @@ -6,7 +6,7 @@ import { NowPosition, } from '@typings/types'; -const useGetWorkplaceData = ( +export const useGetWorkplaceData = ( nowPosition: NowPosition, mapPosition: MapPosition, ) => { @@ -23,4 +23,16 @@ const useGetWorkplaceData = ( return { data, isLoading, isError, refetch }; }; -export default useGetWorkplaceData; +export const useGetRecommendData = (isLogin: boolean, isUser: boolean) => { + const { data, isLoading, isError } = useQuery({ + queryKey: ['recommendWorkPlace', isLogin, isUser], + queryFn: () => getRecommendWorkPlace(), + enabled: isLogin && isUser, + }); + + return { + data: (data ?? []) as GetPositionWorkPlaceData[], + isLoading, + isError, + }; +}; diff --git a/src/pages/MainPage/index.tsx b/src/pages/MainPage/index.tsx index 5c7ba7f..b371b01 100644 --- a/src/pages/MainPage/index.tsx +++ b/src/pages/MainPage/index.tsx @@ -1,11 +1,16 @@ import MainLayout from '@layouts/MainLayout'; import HeaderNoTitle from '@layouts/HeaderNoTitle'; import BottomNavigation from '@layouts/BottomNavigation'; -import { useEffect } from 'react'; import usePositionStore from '@store/positionStore'; +import useAuthStore from '@store/authStore'; +import { useEffect, useState } from 'react'; +import { getRole } from '@utils/auth'; import MainList from './components/MainList'; import KakaoMap from './components/KakaoMap'; -import useGetWorkplaceData from './hooks/useGetWorkplaceData'; +import { + useGetWorkplaceData, + useGetRecommendData, +} from './hooks/useGetWorkplaceData'; const MainPage = () => { const { mapPosition, nowPosition } = usePositionStore(); @@ -15,25 +20,55 @@ const MainPage = () => { longitude: nowPosition.center.lng, }; + // 위치별 조회 데이터 const { data, isLoading, isError } = useGetWorkplaceData( position, mapPosition, ); - // 스크롤 상단으로 이동 + // 비로그인 / 사업자 / 사용자 확인 + const { isLogin } = useAuthStore(); + const [isUser, setIsUser] = useState(false); + useEffect(() => { - window.scrollTo(0, 0); - }, []); + if (isLogin) { + const role = getRole(); + if (role === 'ROLE_USER') { + setIsUser(true); + } + } + }, [isLogin]); + + // 사업장 추천 데이터 + const { + data: recommendData, + isLoading: isRecommendLoading, + isError: isRecommendError, + } = useGetRecommendData(isLogin, isUser); + + // 선택한 탭 + const [activeTab, setActiveTab] = useState('주변 스터디룸'); return ( <> - + diff --git a/src/typings/types.ts b/src/typings/types.ts index 6100131..afc1b53 100644 --- a/src/typings/types.ts +++ b/src/typings/types.ts @@ -290,7 +290,7 @@ export interface GetPositionWorkPlaceData { reviewCount: number; positionLat: number; // positionLon: number; - distance: number; + distance?: number; } // 특정 사업자의 사업장