From e0ca658f2a6bf8f374839612a1811e9a2e47e07b Mon Sep 17 00:00:00 2001 From: HBSPS Date: Fri, 4 Oct 2024 21:25:36 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=EC=B6=94=EC=B2=9C=20=EC=97=AC?= =?UTF-8?q?=ED=96=89=EC=A7=80=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=84=88?= =?UTF-8?q?=EB=B9=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react-native/src/components/home/contents/PopularSpot.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/src/components/home/contents/PopularSpot.tsx b/packages/react-native/src/components/home/contents/PopularSpot.tsx index df5c0e46..d0f246a6 100644 --- a/packages/react-native/src/components/home/contents/PopularSpot.tsx +++ b/packages/react-native/src/components/home/contents/PopularSpot.tsx @@ -18,7 +18,7 @@ const CONTENTS: PopularSpotContent[] = [ content: "구룡포 일본인 가옥거리는 '동백꽃 필 무렵'의 주요 촬영지 중 하나로, 드라 마의 포스터에도 등장한 바로 그 장소입니다. 이곳에는 주인공 동백이가 운영하던 까멜리아도 자리하고 있어, 드라마 속 장면들이 현실에서 그대로 펼쳐지는 듯한 분위기를 자아냅니다. 좁은 골목길과 고즈넉한 건물들이 어우러져 동백이의 일상과 따뜻한 사랑 이야기가 그려졌던 공간의 감성을 고스란히 느낄 수 있으며, 동백이의 삶 이 우리 눈앞에 펼쳐지는 듯한 특별한 경험을 할 수 있습니다.", image: require('../../../assets/home/dongbaek.png'), - imageType: 'poster', + imageType: 'wide', }, { title: '도깨비', From bc517f9f7fc85c1ef8e7078f47a0420dc4fbcef9 Mon Sep 17 00:00:00 2001 From: HBSPS Date: Fri, 4 Oct 2024 21:31:25 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20useLocation=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=ED=9B=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/apis/queries/quiz/useQuizzesQuery.ts | 6 +---- .../react-native/src/hooks/useLocation.ts | 23 +++++++++++++++++++ .../src/pages/Gamification/Gamification.tsx | 17 +++----------- 3 files changed, 27 insertions(+), 19 deletions(-) create mode 100644 packages/react-native/src/hooks/useLocation.ts diff --git a/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts b/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts index f01aeebe..15e025d8 100644 --- a/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts +++ b/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts @@ -3,11 +3,7 @@ import useAuthAxios from '@/apis/useAuthAxios'; import { City, Region } from '@/constants/CITY'; import { ServerResponse } from '@/types/response'; import QUERY_KEYS from '@/constants/QUERY_KEYS'; - -export interface Location { - latitude?: number; - longitude?: number; -} +import { Location } from '@/hooks/useLocation'; export interface QuizzesResponse { quizId: number; diff --git a/packages/react-native/src/hooks/useLocation.ts b/packages/react-native/src/hooks/useLocation.ts new file mode 100644 index 00000000..38153a69 --- /dev/null +++ b/packages/react-native/src/hooks/useLocation.ts @@ -0,0 +1,23 @@ +import { useState, useEffect } from 'react'; +import useGeolocation from './useGeolocation'; + +export interface Location { + latitude?: number; + longitude?: number; +} + +export default function useLocation() { + const { getGeolocation } = useGeolocation(); + const [location, setLocation] = useState(); + + useEffect(() => { + getGeolocation().then((res) => { + setLocation({ + latitude: res?.coords.latitude, + longitude: res?.coords.longitude, + }); + }); + }, []); + + return { location }; +} diff --git a/packages/react-native/src/pages/Gamification/Gamification.tsx b/packages/react-native/src/pages/Gamification/Gamification.tsx index f65fa2c1..88d58f08 100644 --- a/packages/react-native/src/pages/Gamification/Gamification.tsx +++ b/packages/react-native/src/pages/Gamification/Gamification.tsx @@ -1,26 +1,15 @@ -import { useEffect, useState } from 'react'; import QuizLoading from '@components/gamification/QuizLoading'; import QuizSlider from '@components/gamification/QuizSlider'; import withSuspense from '@/components/HOC/withSuspense'; -import useGeolocation from '@/hooks/useGeolocation'; -import useQuizzesQuery, { Location } from '@/apis/queries/quiz/useQuizzesQuery'; +import useQuizzesQuery from '@/apis/queries/quiz/useQuizzesQuery'; import NoQuiz from '@/components/gamification/NoQuiz'; +import useLocation from '@/hooks/useLocation'; export default withSuspense( function Gamification() { - const { getGeolocation } = useGeolocation(); - const [location, setLocation] = useState(); + const { location } = useLocation(); const { data } = useQuizzesQuery({ location }); - useEffect(() => { - getGeolocation().then((res) => { - setLocation({ - latitude: res?.coords.latitude, - longitude: res?.coords.longitude, - }); - }); - }, []); - if (!location?.latitude || !location.longitude) { return ; } From 430d353ffba356db3ed6888059ba94559fbea9b2 Mon Sep 17 00:00:00 2001 From: HBSPS Date: Wed, 9 Oct 2024 16:10:26 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=ED=99=88=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EB=82=B4=20=EC=A3=BC=EB=B3=80=20SPOT=20=EC=98=81=EC=97=AD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/apis/queries/home/useHomeSpotQuery.ts | 2 ++ .../apis/queries/home/useNearbySoptQuery.ts | 27 +++++++++++++++++++ .../src/components/common/Card.tsx | 3 ++- .../src/constants/MILLISECONDS.ts | 6 +++++ .../react-native/src/constants/QUERY_KEYS.ts | 1 + packages/react-native/src/pages/Home/Home.tsx | 14 ++++++++++ 6 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts create mode 100644 packages/react-native/src/constants/MILLISECONDS.ts diff --git a/packages/react-native/src/apis/queries/home/useHomeSpotQuery.ts b/packages/react-native/src/apis/queries/home/useHomeSpotQuery.ts index 2d245cde..496c382c 100644 --- a/packages/react-native/src/apis/queries/home/useHomeSpotQuery.ts +++ b/packages/react-native/src/apis/queries/home/useHomeSpotQuery.ts @@ -3,6 +3,7 @@ import { ServerResponse } from '@/types/response'; import useAuthAxios from '../../useAuthAxios'; import { SpotCardData } from '@/types/spot'; import QUERY_KEYS from '@/constants/QUERY_KEYS'; +import { MILLISECONDS } from '@/constants/MILLISECONDS'; export default function useHomeSpotQuery() { const authAxios = useAuthAxios(); @@ -17,5 +18,6 @@ export default function useHomeSpotQuery() { return useSuspenseQuery({ queryKey: [QUERY_KEYS.HOME], queryFn: getHomeSpot, + staleTime: 10 * MILLISECONDS.ONE_MINUTE, }); } diff --git a/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts b/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts new file mode 100644 index 00000000..90bedfa7 --- /dev/null +++ b/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts @@ -0,0 +1,27 @@ +import { useSuspenseQuery } from '@tanstack/react-query'; +import useAuthAxios from '@/apis/useAuthAxios'; +import { Location } from '@/hooks/useLocation'; +import { ServerResponse } from '@/types/response'; +import { MySpotResponse } from '../mypage/useMySpotsQuery'; +import QUERY_KEYS from '@/constants/QUERY_KEYS'; +import { MILLISECONDS } from '@/constants/MILLISECONDS'; + +export default function useNeearbySpotQuery(location: Location | undefined) { + const authAxios = useAuthAxios(); + + const getNearbySpot = async () => { + if (!location || !location.latitude || !location.longitude) return []; + + const response = await authAxios.get>( + `/api/spot/nearby?latitude=${location.latitude}&longitude=${location.longitude}`, + ); + + return response.data.result; + }; + + return useSuspenseQuery({ + queryKey: [QUERY_KEYS.NEARBY_SPOT, location], + queryFn: getNearbySpot, + staleTime: 10 * MILLISECONDS.ONE_MINUTE, + }); +} diff --git a/packages/react-native/src/components/common/Card.tsx b/packages/react-native/src/components/common/Card.tsx index 7b125675..6d063fff 100644 --- a/packages/react-native/src/components/common/Card.tsx +++ b/packages/react-native/src/components/common/Card.tsx @@ -8,9 +8,10 @@ import { StackNavigation } from '@/types/navigation'; import { getDisplayRegion } from '@/utils/getDisplayRegionName'; import useSpotLikeMutation from '@/apis/mutations/useSpotLikeMutation'; import MutationLoadingModal from './MutationLoadingModal'; +import { MySpotResponse } from '@/apis/queries/mypage/useMySpotsQuery'; interface CardProps { - data: SpotCardData; + data: SpotCardData | MySpotResponse; size?: number; } diff --git a/packages/react-native/src/constants/MILLISECONDS.ts b/packages/react-native/src/constants/MILLISECONDS.ts new file mode 100644 index 00000000..54be87a3 --- /dev/null +++ b/packages/react-native/src/constants/MILLISECONDS.ts @@ -0,0 +1,6 @@ +export const MILLISECONDS = { + ONE_SECOND: 1_000, + ONE_MINUTE: 60_000, + ONE_HOUR: 3_600_000, + ONE_DAY: 86_400_000, +} as const; diff --git a/packages/react-native/src/constants/QUERY_KEYS.ts b/packages/react-native/src/constants/QUERY_KEYS.ts index 8f469b28..8a872bc6 100644 --- a/packages/react-native/src/constants/QUERY_KEYS.ts +++ b/packages/react-native/src/constants/QUERY_KEYS.ts @@ -18,6 +18,7 @@ const QUERY_KEYS = { MY_LEVEL: 'myLevel', BADGE_HISTORY: 'badgeHistory', SCHEDULES: 'schedules', + NEARBY_SPOT: 'nearbySpot', }; export default QUERY_KEYS; diff --git a/packages/react-native/src/pages/Home/Home.tsx b/packages/react-native/src/pages/Home/Home.tsx index 5ca3faa9..4fce30bf 100644 --- a/packages/react-native/src/pages/Home/Home.tsx +++ b/packages/react-native/src/pages/Home/Home.tsx @@ -11,13 +11,18 @@ import withSuspense from '@/components/HOC/withSuspense'; import useHomeSpotQuery from '@/apis/queries/home/useHomeSpotQuery'; import SPOTLogo from '@/assets/SPOTLogo'; import HOME_CONTENTS from '@/constants/HOME_CONTENTS'; +import useLocation from '@/hooks/useLocation'; +import useNeearbySpotQuery from '@/apis/queries/home/useNearbySoptQuery'; interface HomeScreenProps { navigation: StackNavigation<'Home/Main'>; } export default withSuspense(function Home({ navigation }: HomeScreenProps) { + const { location } = useLocation(); + const { profile } = useProfileQuery(); + const { data: nearbySpots } = useNeearbySpotQuery(location); const { data: homeSpots } = useHomeSpotQuery(); return ( @@ -51,6 +56,15 @@ export default withSuspense(function Home({ navigation }: HomeScreenProps) { renderItem={({ item }) => } /> + {nearbySpots.length > 0 && ( + + } + /> + + )} Date: Wed, 9 Oct 2024 16:43:46 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20useLocation=20useEffect=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apis/queries/home/useNearbySoptQuery.ts | 9 ++++--- .../src/apis/queries/quiz/useQuizzesQuery.ts | 25 ++++++++----------- .../react-native/src/hooks/useLocation.ts | 21 ++++++++-------- .../src/pages/Gamification/Gamification.tsx | 8 ++---- packages/react-native/src/pages/Home/Home.tsx | 2 +- 5 files changed, 30 insertions(+), 35 deletions(-) diff --git a/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts b/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts index 90bedfa7..8fa5ad95 100644 --- a/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts +++ b/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts @@ -6,14 +6,17 @@ import { MySpotResponse } from '../mypage/useMySpotsQuery'; import QUERY_KEYS from '@/constants/QUERY_KEYS'; import { MILLISECONDS } from '@/constants/MILLISECONDS'; -export default function useNeearbySpotQuery(location: Location | undefined) { +export default function useNeearbySpotQuery( + location: Promise, +) { const authAxios = useAuthAxios(); const getNearbySpot = async () => { - if (!location || !location.latitude || !location.longitude) return []; + const res = await location; + if (!res || !res.latitude || !res.longitude) return []; const response = await authAxios.get>( - `/api/spot/nearby?latitude=${location.latitude}&longitude=${location.longitude}`, + `/api/spot/nearby?latitude=${res.latitude}&longitude=${res.longitude}`, ); return response.data.result; diff --git a/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts b/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts index 15e025d8..8ec53c9f 100644 --- a/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts +++ b/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts @@ -15,27 +15,24 @@ export interface QuizzesResponse { filterImage: string; } -interface UseQuizzesQueryParams { - location?: Location; -} - -export default function useQuizzesQuery({ location }: UseQuizzesQueryParams) { +export default function useQuizzesQuery( + location: Promise, +) { const authAxios = useAuthAxios(); - const getQuizzes = async (locations: Location) => { + const getQuizzes = async () => { + const res = await location; + if (!res || !res.latitude || !res.longitude) return []; + const result = await authAxios.get>( - `/api/spot?longitude=${locations.longitude}&latitude=${locations.latitude}`, + `/api/spot?longitude=${res.longitude}&latitude=${res.latitude}`, ); + return result.data.result; }; + return useSuspenseQuery({ queryKey: [QUERY_KEYS.QUIZZES, location], - queryFn: () => { - if (!location?.latitude || !location.longitude) { - return null; - } - - return getQuizzes(location); - }, + queryFn: getQuizzes, }); } diff --git a/packages/react-native/src/hooks/useLocation.ts b/packages/react-native/src/hooks/useLocation.ts index 38153a69..9feeec9f 100644 --- a/packages/react-native/src/hooks/useLocation.ts +++ b/packages/react-native/src/hooks/useLocation.ts @@ -1,4 +1,3 @@ -import { useState, useEffect } from 'react'; import useGeolocation from './useGeolocation'; export interface Location { @@ -8,16 +7,16 @@ export interface Location { export default function useLocation() { const { getGeolocation } = useGeolocation(); - const [location, setLocation] = useState(); - useEffect(() => { - getGeolocation().then((res) => { - setLocation({ - latitude: res?.coords.latitude, - longitude: res?.coords.longitude, - }); - }); - }, []); + const fetchLocation = async (): Promise => { + const res = await getGeolocation(); + if (!res) return undefined; - return { location }; + return { + latitude: res.coords.latitude, + longitude: res.coords.longitude, + }; + }; + + return fetchLocation(); // Promise 반환 } diff --git a/packages/react-native/src/pages/Gamification/Gamification.tsx b/packages/react-native/src/pages/Gamification/Gamification.tsx index 88d58f08..50670dbf 100644 --- a/packages/react-native/src/pages/Gamification/Gamification.tsx +++ b/packages/react-native/src/pages/Gamification/Gamification.tsx @@ -7,12 +7,8 @@ import useLocation from '@/hooks/useLocation'; export default withSuspense( function Gamification() { - const { location } = useLocation(); - const { data } = useQuizzesQuery({ location }); - - if (!location?.latitude || !location.longitude) { - return ; - } + const location = useLocation(); + const { data } = useQuizzesQuery(location); if (!data || data?.length === 0) { return ; diff --git a/packages/react-native/src/pages/Home/Home.tsx b/packages/react-native/src/pages/Home/Home.tsx index 4fce30bf..bf1c5cd0 100644 --- a/packages/react-native/src/pages/Home/Home.tsx +++ b/packages/react-native/src/pages/Home/Home.tsx @@ -19,7 +19,7 @@ interface HomeScreenProps { } export default withSuspense(function Home({ navigation }: HomeScreenProps) { - const { location } = useLocation(); + const location = useLocation(); const { profile } = useProfileQuery(); const { data: nearbySpots } = useNeearbySpotQuery(location); From 3700dd0c380aa2296dc5f969f7ce946d41adb746 Mon Sep 17 00:00:00 2001 From: HBSPS Date: Wed, 9 Oct 2024 16:52:41 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20useLocation=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/apis/queries/home/useNearbySoptQuery.ts | 7 +++---- .../react-native/src/apis/queries/quiz/useQuizzesQuery.ts | 7 +++---- .../react-native/src/pages/Gamification/Gamification.tsx | 4 +--- packages/react-native/src/pages/Home/Home.tsx | 5 +---- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts b/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts index 8fa5ad95..380465cf 100644 --- a/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts +++ b/packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts @@ -1,15 +1,14 @@ import { useSuspenseQuery } from '@tanstack/react-query'; import useAuthAxios from '@/apis/useAuthAxios'; -import { Location } from '@/hooks/useLocation'; +import useLocation from '@/hooks/useLocation'; import { ServerResponse } from '@/types/response'; import { MySpotResponse } from '../mypage/useMySpotsQuery'; import QUERY_KEYS from '@/constants/QUERY_KEYS'; import { MILLISECONDS } from '@/constants/MILLISECONDS'; -export default function useNeearbySpotQuery( - location: Promise, -) { +export default function useNeearbySpotQuery() { const authAxios = useAuthAxios(); + const location = useLocation(); const getNearbySpot = async () => { const res = await location; diff --git a/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts b/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts index 8ec53c9f..0993821a 100644 --- a/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts +++ b/packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts @@ -3,7 +3,7 @@ import useAuthAxios from '@/apis/useAuthAxios'; import { City, Region } from '@/constants/CITY'; import { ServerResponse } from '@/types/response'; import QUERY_KEYS from '@/constants/QUERY_KEYS'; -import { Location } from '@/hooks/useLocation'; +import useLocation from '@/hooks/useLocation'; export interface QuizzesResponse { quizId: number; @@ -15,10 +15,9 @@ export interface QuizzesResponse { filterImage: string; } -export default function useQuizzesQuery( - location: Promise, -) { +export default function useQuizzesQuery() { const authAxios = useAuthAxios(); + const location = useLocation(); const getQuizzes = async () => { const res = await location; diff --git a/packages/react-native/src/pages/Gamification/Gamification.tsx b/packages/react-native/src/pages/Gamification/Gamification.tsx index 50670dbf..01286fa2 100644 --- a/packages/react-native/src/pages/Gamification/Gamification.tsx +++ b/packages/react-native/src/pages/Gamification/Gamification.tsx @@ -3,12 +3,10 @@ import QuizSlider from '@components/gamification/QuizSlider'; import withSuspense from '@/components/HOC/withSuspense'; import useQuizzesQuery from '@/apis/queries/quiz/useQuizzesQuery'; import NoQuiz from '@/components/gamification/NoQuiz'; -import useLocation from '@/hooks/useLocation'; export default withSuspense( function Gamification() { - const location = useLocation(); - const { data } = useQuizzesQuery(location); + const { data } = useQuizzesQuery(); if (!data || data?.length === 0) { return ; diff --git a/packages/react-native/src/pages/Home/Home.tsx b/packages/react-native/src/pages/Home/Home.tsx index bf1c5cd0..c64eb1a5 100644 --- a/packages/react-native/src/pages/Home/Home.tsx +++ b/packages/react-native/src/pages/Home/Home.tsx @@ -11,7 +11,6 @@ import withSuspense from '@/components/HOC/withSuspense'; import useHomeSpotQuery from '@/apis/queries/home/useHomeSpotQuery'; import SPOTLogo from '@/assets/SPOTLogo'; import HOME_CONTENTS from '@/constants/HOME_CONTENTS'; -import useLocation from '@/hooks/useLocation'; import useNeearbySpotQuery from '@/apis/queries/home/useNearbySoptQuery'; interface HomeScreenProps { @@ -19,10 +18,8 @@ interface HomeScreenProps { } export default withSuspense(function Home({ navigation }: HomeScreenProps) { - const location = useLocation(); - const { profile } = useProfileQuery(); - const { data: nearbySpots } = useNeearbySpotQuery(location); + const { data: nearbySpots } = useNeearbySpotQuery(); const { data: homeSpots } = useHomeSpotQuery(); return (