Skip to content

feat: search api연동 #73

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 7 commits into from
Sep 24, 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 @@ -6,6 +6,7 @@ import QUERY_KEYS from '@/constants/QUERY_KEYS';

interface UseAroundSpotQueryParams {
id: number;
workId: number;
}

interface AroundSpotResponse {
Expand All @@ -14,12 +15,15 @@ interface AroundSpotResponse {
accomodation: SpotResponse[];
}

export default function useAroundSpotQuery({ id }: UseAroundSpotQueryParams) {
export default function useAroundSpotQuery({
id,
workId,
}: UseAroundSpotQueryParams) {
const authAxios = useAuthAxios();

const getAroundSpot = async () => {
const result = await authAxios.get<ServerResponse<AroundSpotResponse>>(
`/api/spot/${id}/arounds`,
`/api/spot/${id}/arounds?workId=${workId}`,
);
return result.data.result;
};
Expand Down
10 changes: 8 additions & 2 deletions packages/react-native/src/apis/queries/detail/useDetailQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@ interface DetailResponse {
posterUrl: string;
}

export default function useDetailQuery(id: number) {
export default function useDetailQuery({
id,
workId,
}: {
id: number;
workId: number;
}) {
const authAxios = useAuthAxios();
const getSpotAroundInfo = async () => {
const result = await authAxios.get<ServerResponse<DetailResponse>>(
`/api/spot/${id}`,
`/api/spot/${id}?workId=${workId}`,
);
return result.data.result;
};
Expand Down
39 changes: 39 additions & 0 deletions packages/react-native/src/apis/queries/useSearchQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useSuspenseQuery } from '@tanstack/react-query';
import { City, Region } from '@/constants/CITY';
import useAuthAxios from '../useAuthAxios';
import { ServerResponse } from '@/types/response';
import QUERY_KEYS from '@/constants/QUERY_KEYS';

interface UseSearchQueryParams {
keyword: string;
}

interface SearchResponse {
id: number;
contentId: number;
name: string;
region: Region;
city: City;
workId: number;
workName: string;
posterUrl: string;
quote: string;
isLiked: boolean;
likeCount: number;
}

export default function useSearchQuery({ keyword }: UseSearchQueryParams) {
const authAxios = useAuthAxios();
const search = async () => {
const result = await authAxios.get<ServerResponse<SearchResponse[]>>(
`/api/spot/search?keyword=${keyword}`,
);

return result.data.result;
};

return useSuspenseQuery({
queryKey: [QUERY_KEYS.SEARCH, keyword],
queryFn: search,
});
}
23 changes: 18 additions & 5 deletions packages/react-native/src/components/common/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,17 @@ interface CardProps {
}

function Default({ data, size = 260 }: CardProps) {
const { isLiked, name, region, city, posterUrl, likeCount, contentId, id } =
data;
const {
isLiked,
name,
region,
city,
posterUrl,
likeCount,
contentId,
id,
workId,
} = data;
const navigation = useNavigation<StackNavigation<'Home/Search'>>();

return (
Expand All @@ -24,7 +33,9 @@ function Default({ data, size = 260 }: CardProps) {
>
<TouchableOpacity
className="flex-1 justify-end bg-black/40"
onPress={() => navigation.navigate('Home/Detail', { contentId, id })}
onPress={() =>
navigation.navigate('Home/Detail', { contentId, id, workId })
}
activeOpacity={1}
>
<View className="flex-row justify-end items-center">
Expand Down Expand Up @@ -61,7 +72,7 @@ function Default({ data, size = 260 }: CardProps) {
}

function Small({ data, size = 180 }: CardProps) {
const { name, region, city, posterUrl, contentId, id } = data;
const { name, region, city, posterUrl, contentId, id, workId } = data;
const navigation = useNavigation<StackNavigation<'Home/Search'>>();

return (
Expand All @@ -72,7 +83,9 @@ function Small({ data, size = 180 }: CardProps) {
>
<TouchableOpacity
className="flex-1 justify-end bg-black/40"
onPress={() => navigation.navigate('Home/Detail', { contentId, id })}
onPress={() =>
navigation.navigate('Home/Detail', { contentId, id, workId })
}
>
<View className="p-2.5 gap-2">
<View>
Expand Down
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 @@ -12,6 +12,7 @@ const QUERY_KEYS = {
TRIP_PLAN_DETAIL: 'tripPlanDetail',
EDIT_PLAN: 'editPlan',
SPOT_DETAIL: 'spotDetail',
SEARCH: 'search',
};

export default QUERY_KEYS;
4 changes: 2 additions & 2 deletions packages/react-native/src/pages/Detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import { getDisplayRegion } from '@/utils/getDisplayRegionName';
const Detail = withSuspense(() => {
const route = useRoute<StackRouteProps<'Home/Detail'>>();
const navigation = useNavigation<StackNavigation<'Home/Detail'>>();
const { id, contentId: paramsContentId } = route.params;
const { id, contentId: paramsContentId, workId } = route.params;

const { data } = useDetailQuery(paramsContentId);
const { data } = useDetailQuery({ id: paramsContentId, workId });
const { like, cancelLike, isLikePending, isCancelLikePending } =
useSpotLikeMutation({ contentId: paramsContentId });

Expand Down
4 changes: 2 additions & 2 deletions packages/react-native/src/pages/Detail/DetailInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { StackRouteProps } from '@/types/navigation';

export default function DetailInfo() {
const route = useRoute<StackRouteProps<'Home/Detail'>>();
const { contentId } = route.params;
const { data } = useDetailQuery(contentId);
const { contentId, workId } = route.params;
const { data } = useDetailQuery({ id: contentId, workId });

return (
<ScrollView
Expand Down
4 changes: 2 additions & 2 deletions packages/react-native/src/pages/Detail/DetailSpot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export default withSuspense(function DetailSpot() {
const { list, toggleItem } = useArrayToggle<SpotResponse>();
const navigation = useNavigation<StackNavigation<'Home/Detail'>>();

const { contentId } = route.params;
const { contentId, workId } = route.params;

const { data } = useAroundSpotQuery({ id: contentId });
const { data } = useAroundSpotQuery({ id: contentId, workId });

const startLongPress = (spot: SpotResponse) => {
if (!longPressMode) {
Expand Down
101 changes: 40 additions & 61 deletions packages/react-native/src/pages/Search.tsx
Original file line number Diff line number Diff line change
@@ -1,91 +1,70 @@
import { useRef, useState } from 'react';
import { useRoute } from '@react-navigation/native';
import { View } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import { TouchableOpacity, View } from 'react-native';
import { Font } from 'design-system';
import Carousel, { ICarouselInstance } from 'react-native-reanimated-carousel';
import BackGroundGradient from '@/layouts/BackGroundGradient';
import { SpotCardData } from '@/types/spot';
import Card from '@/components/common/Card';
import WordBreak from '@/components/common/WordBreak';
import Header from '@/components/common/Header';
import { StackRouteProps } from '@/types/navigation';
import { StackNavigation, StackRouteProps } from '@/types/navigation';
import { DEFAULT_COLOR } from '@/constants/DEFAULT_COLOR';
import useSearchQuery from '@/apis/queries/useSearchQuery';
import withSuspense from '@/components/HOC/withSuspense';

// FIXME: 추후 제거
const mockData: SpotCardData[] = [
{
contentId: 10,
name: '주문진 방파제',
region: 1,
city: 20,

posterUrl:
'https://i.namu.wiki/i/oIbSW8G0ldkxIJGYLf9e9OzO1n2PkDJMu78IBDV1wh7v06rSdSvlzGUc4znFOc7EH0xi1OLJx3HqzfJgkb514Oj0BPqXU2m0dWl0wwY8coA1A7rQiOcKlLpUfEZ45Ee7bKskmI3RSb760_xrYzysTw.webp',
isLiked: true,
likeCount: 21,
quote: '',
workName: '도깨비',
workId: 1,
},
{
contentId: 20,
name: '룰루랄라',
region: 1,
city: 20,

posterUrl:
'https://i.namu.wiki/i/5YW8uWfQIeY4JG56CkWX8tL8hzeQxsQ9o8aXoLkHiMxHkTJLyRzC0RHdd6zJHctNQYXfhHqddAg48LhqHIgdyTRRH-awxeCSoCSIT04XlPAx_ciulV9hfEPPdir_zbiT0mtWDNtr9a1hewqNhwpAbg.webp',
isLiked: false,
likeCount: 12,
quote: '',
workName: '도깨비',
workId: 1,
},
{
contentId: 30,
name: '룰루랄라2',
region: 1,
city: 20,

posterUrl:
'https://i.namu.wiki/i/x9m5nUyjJvqSTSPX5EczIy02UrLrzZ7ndKHhsh2yl7SXKRQMGwHCtGM-vvfWI6ySufjf_2YXXoZezjSNgDSFRyvilXPootx2PKAitdNBvEizIkMBYCCnZxu98NMSudE83LkWHXhWIVNsCXBblDzctQ.webp',
isLiked: false,
likeCount: 12,
quote: '',
workName: '도깨비',
workId: 1,
},
];

const mockDescription =
'"너와 함께한 시간 모두 눈부셨다. 날이 좋아서, 날이 좋지 않아서, 날이 적당해서 모든 날이 좋았다."';
export default withSuspense(function Search() {
const route = useRoute<StackRouteProps<'Home/Search'>>();
const { title } = route.params;
const { data } = useSearchQuery({ keyword: title });
const navigation = useNavigation<StackNavigation<'Home/Search'>>();

export default function Search() {
const [carouselIndex, setCarouselIndex] = useState(0);
const carouselRef = useRef<ICarouselInstance>(null);
const route = useRoute<StackRouteProps<'Home/Search'>>();
const { title } = route.params;

const onProgressChange = () => {
if (!carouselRef.current) return;
const index = carouselRef.current.getCurrentIndex();
setCarouselIndex(index);
};

if (data.length === 0) {
return (
<BackGroundGradient withoutScroll>
<Header />
<View className="flex-1 justify-center items-center">
<Font type="body1" color="white">
검색결과가 없어요.
</Font>
<Font type="body1" color="white">
다른 작품을 검색해볼까요?
</Font>
<TouchableOpacity
className="bg-Button-red rounded-xl px-4 py-2 mt-4"
onPress={() => navigation.navigate('Home/Main')}
>
<Font type="body2" color="white">
돌아가기
</Font>
</TouchableOpacity>
</View>
</BackGroundGradient>
);
}

return (
<BackGroundGradient>
<Header />
<View className="items-center">
<Font.Bold type="mainTitle" color="white">
{title}
{data[carouselIndex].workName}
</Font.Bold>
</View>
<View className="mt-4 justify-center items-center">
<WordBreak
width={220}
type="body1"
color="white"
content={mockDescription}
content={data[carouselIndex].quote}
/>
</View>
<View className="mt-5 mb-20">
Expand All @@ -101,13 +80,13 @@ export default function Search() {
width={260}
height={350}
mode="horizontal-stack"
modeConfig={{ showLength: mockData.length }}
modeConfig={{ showLength: data.length }}
loop={false}
data={mockData}
data={data}
renderItem={({ item }) => <Card data={item} />}
/>
<View className="flex-row justify-center gap-2">
{mockData.map((_, index) => (
{data.map((_, index) => (
<View
key={index}
className="w-1 h-1 rounded-full"
Expand All @@ -123,4 +102,4 @@ export default function Search() {
</View>
</BackGroundGradient>
);
}
});
5 changes: 3 additions & 2 deletions packages/react-native/src/routes/DetailTabNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const Tab = createMaterialTopTabNavigator();

export default function DetailTabNavigator() {
const route = useRoute<StackRouteProps<'Home/Detail'>>();
const { id, contentId } = route.params;
const { id, contentId, workId } = route.params;

return (
<Tab.Navigator
Expand Down Expand Up @@ -42,13 +42,14 @@ export default function DetailTabNavigator() {
initialParams={{
id,
contentId,
workId,
}}
/>
<Tab.Screen
name="Detail/Spot"
component={DetailSpot}
options={{ tabBarLabel: 'SPOT!' }}
initialParams={{ id, contentId }}
initialParams={{ id, contentId, workId }}
/>
</Tab.Navigator>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/src/types/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export type StackParamList = {

'Home/Main': undefined;
'Home/Search': { title: string };
'Home/Detail': { contentId: number; id: number };
'Home/Detail': { contentId: number; id: number; workId: number };
'Home/AddSpot': {
spots: SpotResponse[];
};
Expand Down
Loading