diff --git a/packages/react-native/src/apis/mutations/useDeleteSelectedSpotMutation.ts b/packages/react-native/src/apis/mutations/useDeleteSelectedSpotMutation.ts
new file mode 100644
index 00000000..c01dd397
--- /dev/null
+++ b/packages/react-native/src/apis/mutations/useDeleteSelectedSpotMutation.ts
@@ -0,0 +1,25 @@
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import useAuthAxios from '../useAuthAxios';
+import QUERY_KEYS from '@/constants/QUERY_KEYS';
+
+export default function useDeleteSelectedSpotMutation(
+ tripId: number,
+ options?: { onSuccess?: () => void },
+) {
+ const authAxios = useAuthAxios();
+ const queryClient = useQueryClient();
+
+ const deleteSelectedSpots = async (id: number) => {
+ await authAxios.delete(`/api/schedule/selected-spot/${id}`);
+ };
+
+ return useMutation({
+ mutationFn: deleteSelectedSpots,
+ onSuccess: async () => {
+ await queryClient.invalidateQueries({
+ queryKey: [QUERY_KEYS.TRIP_PLAN_DETAIL, tripId],
+ });
+ if (options?.onSuccess) options.onSuccess();
+ },
+ });
+}
diff --git a/packages/react-native/src/apis/mutations/useRecordMutation.ts b/packages/react-native/src/apis/mutations/useRecordMutation.ts
index 5ff46274..3b576b26 100644
--- a/packages/react-native/src/apis/mutations/useRecordMutation.ts
+++ b/packages/react-native/src/apis/mutations/useRecordMutation.ts
@@ -59,6 +59,9 @@ export default function useRecordMutation({
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.RECORDS, location],
});
+ queryClient.invalidateQueries({
+ queryKey: [QUERY_KEYS.MY_BADGES],
+ });
};
const { mutateAsync: postMutate, isPending: isPostPending } = useMutation({
diff --git a/packages/react-native/src/apis/queries/spot/useSpotDetailQuery.ts b/packages/react-native/src/apis/queries/spot/useSpotDetailQuery.ts
index d3f61da6..df47d534 100644
--- a/packages/react-native/src/apis/queries/spot/useSpotDetailQuery.ts
+++ b/packages/react-native/src/apis/queries/spot/useSpotDetailQuery.ts
@@ -9,6 +9,7 @@ interface UseSpotDetailQueryParams {
}
export interface SpotResponse {
+ id: number;
contentId: number;
title: string;
image: string;
diff --git a/packages/react-native/src/components/detail/AroundCard.tsx b/packages/react-native/src/components/detail/AroundCard.tsx
index d06410fc..bcc0bf9d 100644
--- a/packages/react-native/src/components/detail/AroundCard.tsx
+++ b/packages/react-native/src/components/detail/AroundCard.tsx
@@ -1,19 +1,24 @@
import { ImageBackground, TouchableOpacity, View } from 'react-native';
import { Font, CheckBox } from 'design-system';
import { SpotResponse } from '@/apis/queries/spot/useSpotDetailQuery';
+import DotMenuIcon from '@/assets/DotMenuIcon';
interface AroundCardProps {
data: SpotResponse;
+ withMenuIcon?: boolean;
onCardClick: (spot: SpotResponse) => void;
+ onMenuClick?: () => void;
selectedSpots?: SpotResponse[];
selectionMode?: boolean;
}
export default function AroundCard({
data,
+ withMenuIcon,
selectedSpots,
selectionMode,
onCardClick,
+ onMenuClick,
}: AroundCardProps) {
const { image, title } = data;
@@ -43,6 +48,14 @@ export default function AroundCard({
{title}
+ {withMenuIcon && (
+
+
+
+ )}
);
diff --git a/packages/react-native/src/pages/TripPlanner/TripPlannerDetail.tsx b/packages/react-native/src/pages/TripPlanner/TripPlannerDetail.tsx
index fd63fcac..bcef057c 100644
--- a/packages/react-native/src/pages/TripPlanner/TripPlannerDetail.tsx
+++ b/packages/react-native/src/pages/TripPlanner/TripPlannerDetail.tsx
@@ -12,13 +12,26 @@ import AroundCard from '@/components/detail/AroundCard';
import SpotDetailBottomSheet from '@/components/common/SpotDetailBottomSheet';
import useTripPlanMySpotQuery from '@/apis/queries/tripPlan/useTripPlanMySpotQuery';
import Spacing from '@/components/common/Spacing';
+import useDeleteSelectedSpotMutation from '@/apis/mutations/useDeleteSelectedSpotMutation';
+import BottomSheet from '@/components/common/BottomSheet';
+import { SpotResponse } from '@/apis/queries/spot/useSpotDetailQuery';
export default withSuspense(function TripPlannerDetail() {
const route = useRoute>();
const { tripId, region, city, startDate, endDate } = route.params;
const { data } = useTripPlanMySpotQuery({ id: tripId });
const [selectedSpot, setSelectedSpot] = useState();
+ const [targetSpot, setTargetSpot] = useState();
const navigation = useNavigation>();
+ const { mutate: deleteSelectedSpots } = useDeleteSelectedSpotMutation(
+ tripId,
+ { onSuccess: () => setTargetSpot(undefined) },
+ );
+
+ const deleteSpot = () => {
+ if (!targetSpot) return;
+ deleteSelectedSpots(targetSpot.id);
+ };
return (
@@ -66,6 +79,8 @@ export default withSuspense(function TripPlannerDetail() {
renderItem={({ item }) => (
setTargetSpot(item)}
onCardClick={() => setSelectedSpot(item.contentId)}
/>
)}
@@ -80,6 +95,8 @@ export default withSuspense(function TripPlannerDetail() {
renderItem={({ item }) => (
setTargetSpot(item)}
onCardClick={() => setSelectedSpot(item.contentId)}
/>
)}
@@ -94,6 +111,8 @@ export default withSuspense(function TripPlannerDetail() {
renderItem={({ item }) => (
setTargetSpot(item)}
onCardClick={() => setSelectedSpot(item.contentId)}
/>
)}
@@ -106,6 +125,26 @@ export default withSuspense(function TripPlannerDetail() {
selectedDetailSpotId={selectedSpot}
onClose={() => setSelectedSpot(undefined)}
/>
+ setTargetSpot(undefined)}
+ >
+
+
+ {targetSpot?.title}
+
+
+
+
+ 삭제
+
+
+
+
);
});