diff --git a/packages/react-native/src/apis/mutations/useSpotLikeMutation.ts b/packages/react-native/src/apis/mutations/useSpotLikeMutation.ts index 0ad7194b..58bffdfa 100644 --- a/packages/react-native/src/apis/mutations/useSpotLikeMutation.ts +++ b/packages/react-native/src/apis/mutations/useSpotLikeMutation.ts @@ -37,6 +37,9 @@ export default function useSpotLikeMutation({ queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.DETAIL, contentId], }); + queryClient.invalidateQueries({ + queryKey: [QUERY_KEYS.MY_SPOTS], + }); }; const { mutateAsync: like, isPending: isLikePending } = useMutation({ diff --git a/packages/react-native/src/apis/queries/mypage/useMySpotsQuery.ts b/packages/react-native/src/apis/queries/mypage/useMySpotsQuery.ts new file mode 100644 index 00000000..c6602353 --- /dev/null +++ b/packages/react-native/src/apis/queries/mypage/useMySpotsQuery.ts @@ -0,0 +1,29 @@ +import { useSuspenseQuery } from '@tanstack/react-query'; +import useAuthAxios from '@/apis/useAuthAxios'; +import { City, Region } from '@/constants/CITY'; +import QUERY_KEYS from '@/constants/QUERY_KEYS'; +import { ServerResponse } from '@/types/response'; + +interface MySpotResponse { + id: number; + contentId: number; + name: string; + region: Region; + city: City; + workId: number; + posterUrl: string; +} + +export default function useMySpotsQuery() { + const authAxios = useAuthAxios(); + const getMySpots = async () => { + const result = + await authAxios.get>('/api/user/likes'); + return result.data.result; + }; + + return useSuspenseQuery({ + queryFn: getMySpots, + queryKey: [QUERY_KEYS.MY_SPOTS], + }); +} diff --git a/packages/react-native/src/components/mypage/MySpotBlock.tsx b/packages/react-native/src/components/mypage/MySpotBlock.tsx index f87cf1ce..cd7998da 100644 --- a/packages/react-native/src/components/mypage/MySpotBlock.tsx +++ b/packages/react-native/src/components/mypage/MySpotBlock.tsx @@ -1,24 +1,19 @@ import { Font } from 'design-system'; -import { Alert, ImageBackground, TouchableOpacity, View } from 'react-native'; -import DotMenuIcon from '@/assets/DotMenuIcon'; +import { ImageBackground, TouchableOpacity, View } from 'react-native'; interface MySpotBlockProps { - id: number; title: string; - location: string; + location?: string; backgroundImage: string; - date: string; width: number; gap: number; handleClickBlock: () => void; } export default function MySpotBlock({ - id, title, location, backgroundImage, - date, width, gap, handleClickBlock, @@ -33,23 +28,14 @@ export default function MySpotBlock({ className="flex-1 justify-end bg-black/40" onPress={handleClickBlock} > - - + + {title} - + {location} - - {date} - - Alert.alert('메뉴 클릭')} - > - - ); diff --git a/packages/react-native/src/constants/QUERY_KEYS.ts b/packages/react-native/src/constants/QUERY_KEYS.ts index b2c165e2..0113fac3 100644 --- a/packages/react-native/src/constants/QUERY_KEYS.ts +++ b/packages/react-native/src/constants/QUERY_KEYS.ts @@ -13,6 +13,7 @@ const QUERY_KEYS = { EDIT_PLAN: 'editPlan', SPOT_DETAIL: 'spotDetail', SEARCH: 'search', + MY_SPOTS: 'mySpots', }; export default QUERY_KEYS; diff --git a/packages/react-native/src/pages/MyPage.tsx b/packages/react-native/src/pages/MyPage.tsx index 77ce602d..2810508b 100644 --- a/packages/react-native/src/pages/MyPage.tsx +++ b/packages/react-native/src/pages/MyPage.tsx @@ -52,9 +52,9 @@ export default withSuspense(function MyPage({ navigation }: MyPageProps) { > - {/* + - */} + ); diff --git a/packages/react-native/src/pages/MyPage/MySpot.tsx b/packages/react-native/src/pages/MyPage/MySpot.tsx index ec7dc810..c199e50f 100644 --- a/packages/react-native/src/pages/MyPage/MySpot.tsx +++ b/packages/react-native/src/pages/MyPage/MySpot.tsx @@ -1,85 +1,56 @@ -import { Dimensions, FlatList } from 'react-native'; -import { useState } from 'react'; +import { Dimensions, FlatList, View } from 'react-native'; +import { useNavigation } from '@react-navigation/native'; +import { Font } from 'design-system'; import MySpotBlock from '@/components/mypage/MySpotBlock'; -import SpotDetailBottomSheet from '@/components/common/SpotDetailBottomSheet'; - -const mockData = [ - { - id: 1, - title: '여행', - backgroundImage: 'https://cdn.hankyung.com/photo/202208/03.30909476.1.jpg', - location: '주문진 방파제', - date: '2024.01.01', - }, - { - id: 2, - title: '여행', - backgroundImage: 'https://cdn.hankyung.com/photo/202208/03.30909476.1.jpg', - location: '주문진 방파제', - date: '2024.01.02', - }, - { - id: 3, - title: '여행', - backgroundImage: 'https://cdn.hankyung.com/photo/202208/03.30909476.1.jpg', - location: '주문진 방파제', - date: '2024.01.03', - }, - { - id: 4, - title: '여행', - backgroundImage: 'https://cdn.hankyung.com/photo/202208/03.30909476.1.jpg', - location: '주문진 방파제', - date: '2024.01.04', - }, - { - id: 5, - title: '여행', - backgroundImage: 'https://cdn.hankyung.com/photo/202208/03.30909476.1.jpg', - location: '주문진 방파제', - date: '2024.01.05', - }, - { - id: 6, - title: '여행', - backgroundImage: 'https://cdn.hankyung.com/photo/202208/03.30909476.1.jpg', - location: '주문진 방파제', - date: '2024.01.06', - }, -]; +import withSuspense from '@/components/HOC/withSuspense'; +import useMySpotsQuery from '@/apis/queries/mypage/useMySpotsQuery'; +import { getDisplayRegion } from '@/utils/getDisplayRegionName'; +import { StackNavigation } from '@/types/navigation'; const { width } = Dimensions.get('window'); -export default function MySpot() { - const [selectedDetailSpotId, setSelectedDetailSpotId] = useState(); +export default withSuspense(function MySpot() { + const { data: mySpots } = useMySpotsQuery(); + const navigation = useNavigation>(); const numColumns = 2; const paddingHorizontal = 8; const gap = 16; + if (mySpots.length === 0) { + return ( + + + 좋아요한 SPOT이 없어요 + + + ); + } + return ( - <> - ( - setSelectedDetailSpotId(item.id)} - /> - )} - keyExtractor={(item) => item.title + item.location + item.date} - numColumns={numColumns} - /> - setSelectedDetailSpotId(undefined)} - /> - + ( + + navigation.navigate('MyPage/Detail', { + contentId: item.contentId, + id: item.id, + workId: item.workId, + }) + } + /> + )} + keyExtractor={(item) => item.name + item.id + item.contentId} + numColumns={numColumns} + /> ); -} +}); diff --git a/packages/react-native/src/routes/MyPageStackNavigator.tsx b/packages/react-native/src/routes/MyPageStackNavigator.tsx index d40f8a0d..104bc3d2 100644 --- a/packages/react-native/src/routes/MyPageStackNavigator.tsx +++ b/packages/react-native/src/routes/MyPageStackNavigator.tsx @@ -2,6 +2,7 @@ import { createStackNavigator } from '@react-navigation/stack'; import MyPage from '@/pages/MyPage'; import EditProfile from '@/pages/MyPage/EditProfile'; import EditProfileWithNickname from '@/pages/MyPage/EditProfileWithNickname'; +import Detail from '@/pages/Detail'; const Stack = createStackNavigator(); @@ -17,6 +18,7 @@ export default function MyPageStackNavigator() { name="MyPage/EditProfileWithNickname" component={EditProfileWithNickname} /> + ); } diff --git a/packages/react-native/src/types/navigation.ts b/packages/react-native/src/types/navigation.ts index 19e4facd..b4a03cad 100644 --- a/packages/react-native/src/types/navigation.ts +++ b/packages/react-native/src/types/navigation.ts @@ -39,6 +39,7 @@ export type StackParamList = { 'MyPage/Profile': undefined; 'MyPage/EditProfile': { nickname: string }; 'MyPage/EditProfileWithNickname': { nickname: string }; + 'MyPage/Detail': { contentId: number; id: number; workId: number }; 'Home/Main': undefined; 'Home/Search': { title: string };