Skip to content

feat: 홈 화면 내 주변 SPOT 영역 추가 #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -17,5 +18,6 @@ export default function useHomeSpotQuery() {
return useSuspenseQuery({
queryKey: [QUERY_KEYS.HOME],
queryFn: getHomeSpot,
staleTime: 10 * MILLISECONDS.ONE_MINUTE,
});
}
29 changes: 29 additions & 0 deletions packages/react-native/src/apis/queries/home/useNearbySoptQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useSuspenseQuery } from '@tanstack/react-query';
import useAuthAxios from '@/apis/useAuthAxios';
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() {
const authAxios = useAuthAxios();
const location = useLocation();

const getNearbySpot = async () => {
const res = await location;
if (!res || !res.latitude || !res.longitude) return [];

const response = await authAxios.get<ServerResponse<MySpotResponse[]>>(
`/api/spot/nearby?latitude=${res.latitude}&longitude=${res.longitude}`,
);

return response.data.result;
};

return useSuspenseQuery({
queryKey: [QUERY_KEYS.NEARBY_SPOT, location],
queryFn: getNearbySpot,
staleTime: 10 * MILLISECONDS.ONE_MINUTE,
});
}
30 changes: 11 additions & 19 deletions packages/react-native/src/apis/queries/quiz/useQuizzesQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 useLocation from '@/hooks/useLocation';

export interface QuizzesResponse {
quizId: number;
Expand All @@ -19,27 +15,23 @@ export interface QuizzesResponse {
filterImage: string;
}

interface UseQuizzesQueryParams {
location?: Location;
}

export default function useQuizzesQuery({ location }: UseQuizzesQueryParams) {
export default function useQuizzesQuery() {
const authAxios = useAuthAxios();
const location = useLocation();

const getQuizzes = async () => {
const res = await location;
if (!res || !res.latitude || !res.longitude) return [];

const getQuizzes = async (locations: Location) => {
const result = await authAxios.get<ServerResponse<QuizzesResponse[]>>(
`/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,
});
}
3 changes: 2 additions & 1 deletion packages/react-native/src/components/common/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const CONTENTS: PopularSpotContent[] = [
content:
"구룡포 일본인 가옥거리는 '동백꽃 필 무렵'의 주요 촬영지 중 하나로, 드라 마의 포스터에도 등장한 바로 그 장소입니다. 이곳에는 주인공 동백이가 운영하던 까멜리아도 자리하고 있어, 드라마 속 장면들이 현실에서 그대로 펼쳐지는 듯한 분위기를 자아냅니다. 좁은 골목길과 고즈넉한 건물들이 어우러져 동백이의 일상과 따뜻한 사랑 이야기가 그려졌던 공간의 감성을 고스란히 느낄 수 있으며, 동백이의 삶 이 우리 눈앞에 펼쳐지는 듯한 특별한 경험을 할 수 있습니다.",
image: require('../../../assets/home/dongbaek.png'),
imageType: 'poster',
imageType: 'wide',
},
{
title: '도깨비',
Expand Down
6 changes: 6 additions & 0 deletions packages/react-native/src/constants/MILLISECONDS.ts
Original file line number Diff line number Diff line change
@@ -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;
1 change: 1 addition & 0 deletions packages/react-native/src/constants/QUERY_KEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const QUERY_KEYS = {
MY_LEVEL: 'myLevel',
BADGE_HISTORY: 'badgeHistory',
SCHEDULES: 'schedules',
NEARBY_SPOT: 'nearbySpot',
};

export default QUERY_KEYS;
22 changes: 22 additions & 0 deletions packages/react-native/src/hooks/useLocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import useGeolocation from './useGeolocation';

export interface Location {
latitude?: number;
longitude?: number;
}

export default function useLocation() {
const { getGeolocation } = useGeolocation();

const fetchLocation = async (): Promise<Location | undefined> => {
const res = await getGeolocation();
if (!res) return undefined;

return {
latitude: res.coords.latitude,
longitude: res.coords.longitude,
};
};

return fetchLocation(); // Promise 반환
}
21 changes: 2 additions & 19 deletions packages/react-native/src/pages/Gamification/Gamification.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,12 @@
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';

export default withSuspense(
function Gamification() {
const { getGeolocation } = useGeolocation();
const [location, setLocation] = useState<Location>();
const { data } = useQuizzesQuery({ location });

useEffect(() => {
getGeolocation().then((res) => {
setLocation({
latitude: res?.coords.latitude,
longitude: res?.coords.longitude,
});
});
}, []);

if (!location?.latitude || !location.longitude) {
return <QuizLoading />;
}
const { data } = useQuizzesQuery();

if (!data || data?.length === 0) {
return <NoQuiz />;
Expand Down
11 changes: 11 additions & 0 deletions packages/react-native/src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ 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 useNeearbySpotQuery from '@/apis/queries/home/useNearbySoptQuery';

interface HomeScreenProps {
navigation: StackNavigation<'Home/Main'>;
}

export default withSuspense(function Home({ navigation }: HomeScreenProps) {
const { profile } = useProfileQuery();
const { data: nearbySpots } = useNeearbySpotQuery();
const { data: homeSpots } = useHomeSpotQuery();

return (
Expand Down Expand Up @@ -51,6 +53,15 @@ export default withSuspense(function Home({ navigation }: HomeScreenProps) {
renderItem={({ item }) => <Card data={item} size={180} />}
/>
</View>
{nearbySpots.length > 0 && (
<View>
<CardSlider
title="내 주변 SPOT!"
data={nearbySpots}
renderItem={({ item }) => <Card data={item} size={180} />}
/>
</View>
)}
<View>
<CardSlider
title="이 여행지는 어때요?"
Expand Down
Loading