diff --git a/frontend/src/components/pages/travelPlanDetail/TravelPlanDetailPage.tsx b/frontend/src/components/pages/travelPlanDetail/TravelPlanDetailPage.tsx index a0d51b91..4155588f 100644 --- a/frontend/src/components/pages/travelPlanDetail/TravelPlanDetailPage.tsx +++ b/frontend/src/components/pages/travelPlanDetail/TravelPlanDetailPage.tsx @@ -1,6 +1,6 @@ import { useRef, useState } from "react"; import ReactGA from "react-ga4"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { useTravelTransformDetailContext } from "@contexts/TravelTransformDetailProvider"; @@ -18,7 +18,6 @@ import useLeadingDebounce from "@hooks/useLeadingDebounce"; import { DEBOUNCED_TIME } from "@constants/debouncedTime"; import { ROUTE_PATHS_MAP } from "@constants/route"; -import { extractLastPath } from "@utils/extractId"; import getDateRange from "@utils/getDateRange"; import getDaysAndNights from "@utils/getDaysAndNights"; import { isUUID } from "@utils/uuid"; @@ -28,8 +27,7 @@ import theme from "@styles/theme"; import * as S from "./TravelPlanDetailPage.styled"; const TravelPlanDetailPage = () => { - const location = useLocation(); - const id = extractLastPath(location.pathname); + const { id = "" } = useParams(); const { onTransformTravelDetail } = useTravelTransformDetailContext(); const { data, status, error } = useGetTravelPlan(id); diff --git a/frontend/src/components/pages/travelPlanDetail/TravelPlanTodoItem/TravelPlanTodoItem.tsx b/frontend/src/components/pages/travelPlanDetail/TravelPlanTodoItem/TravelPlanTodoItem.tsx index 9b725316..9ef4fd66 100644 --- a/frontend/src/components/pages/travelPlanDetail/TravelPlanTodoItem/TravelPlanTodoItem.tsx +++ b/frontend/src/components/pages/travelPlanDetail/TravelPlanTodoItem/TravelPlanTodoItem.tsx @@ -19,15 +19,15 @@ const TravelPlanTodoItem = ({ todo }: { todo: TravelPlanTodo }) => { return ( { if (!isUUID(id)) mutateUpdateTodoStatus({ - todoId: todo.id as string, - checked: e.target.checked, + todoId: String(todo.id), + isChecked: e.target.checked, }); }} - isChecked={todo.checked ?? false} + isChecked={todo.isChecked ?? false} /> {todo.content} diff --git a/frontend/src/components/pages/travelPlanEdit/TravelPlanEditPage.tsx b/frontend/src/components/pages/travelPlanEdit/TravelPlanEditPage.tsx index cfa12319..39d20920 100644 --- a/frontend/src/components/pages/travelPlanEdit/TravelPlanEditPage.tsx +++ b/frontend/src/components/pages/travelPlanEdit/TravelPlanEditPage.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { useGetTravelPlan } from "@queries/useGetTravelPlan"; import { usePutTravelPlan } from "@queries/usePutTravelPlan"; @@ -27,7 +27,6 @@ import { ERROR_MESSAGE_MAP } from "@constants/errorMessage"; import { FORM_VALIDATIONS_MAP } from "@constants/formValidation"; import { ROUTE_PATHS_MAP } from "@constants/route"; -import { extractID } from "@utils/extractId"; import { extractUTCDate } from "@utils/extractUTCDate"; import * as S from "./TravelPlanEditPage.styled"; @@ -35,8 +34,7 @@ import * as S from "./TravelPlanEditPage.styled"; const TravelPlanEditPage = () => { const navigate = useNavigate(); - const location = useLocation(); - const id = extractID(location.pathname); + const { id = "" } = useParams(); const { data, status, error, isLoading } = useGetTravelPlan(id); @@ -89,9 +87,9 @@ const TravelPlanEditPage = () => { id: Number(id), }, { - onSuccess: (data) => { + onSuccess: () => { handleCloseBottomSheet(); - navigate(ROUTE_PATHS_MAP.travelPlan(data?.data?.id)); + navigate(ROUTE_PATHS_MAP.travelPlan(id)); }, }, ); diff --git a/frontend/src/components/pages/travelPlanRegister/PlaceTodoListItem/PlaceTodoListItem.tsx b/frontend/src/components/pages/travelPlanRegister/PlaceTodoListItem/PlaceTodoListItem.tsx index 7c6f3c1b..d8c0004e 100644 --- a/frontend/src/components/pages/travelPlanRegister/PlaceTodoListItem/PlaceTodoListItem.tsx +++ b/frontend/src/components/pages/travelPlanRegister/PlaceTodoListItem/PlaceTodoListItem.tsx @@ -16,7 +16,7 @@ const PlaceTodoListItem = ({ todo, onChangeContent, onDeleteTodo }: PlaceTodoLis return ( - + { const travelPlanPayload = { title, startDate: extractUTCDate(startDate), days: travelPlanDays }; mutateTravelPlanRegister(travelPlanPayload, { - onSuccess: (data) => { - const travelPlanId = data?.data?.id; + onSuccess: ({ headers: { location } }) => { + const id = extractLastPath(location); handleCloseBottomSheet(); - navigate(ROUTE_PATHS_MAP.travelPlan(travelPlanId)); + navigate(ROUTE_PATHS_MAP.travelPlan(id)); }, }); }; diff --git a/frontend/src/components/pages/travelogueDetail/TravelogueDetailPage.tsx b/frontend/src/components/pages/travelogueDetail/TravelogueDetailPage.tsx index 3d3b5e8d..e04744fb 100644 --- a/frontend/src/components/pages/travelogueDetail/TravelogueDetailPage.tsx +++ b/frontend/src/components/pages/travelogueDetail/TravelogueDetailPage.tsx @@ -1,6 +1,6 @@ import { useRef, useState } from "react"; import ReactGA from "react-ga4"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { useTravelTransformDetailContext } from "@contexts/TravelTransformDetailProvider"; @@ -30,7 +30,6 @@ import { DEBOUNCED_TIME } from "@constants/debouncedTime"; import { ERROR_MESSAGE_MAP } from "@constants/errorMessage"; import { ROUTE_PATHS_MAP } from "@constants/route"; -import { extractID } from "@utils/extractId"; import getDaysAndNights from "@utils/getDaysAndNights"; import theme from "@styles/theme"; @@ -39,8 +38,7 @@ import { SEMANTIC_COLORS } from "@styles/tokens"; import * as S from "./TravelogueDetailPage.styled"; const TravelogueDetailPage = () => { - const location = useLocation(); - const id = extractID(location.pathname); + const { id = "" } = useParams(); const { user } = useUser(); diff --git a/frontend/src/components/pages/travelogueEdit/TravelogueEditPage.tsx b/frontend/src/components/pages/travelogueEdit/TravelogueEditPage.tsx index ab34ec47..b4cade1b 100644 --- a/frontend/src/components/pages/travelogueEdit/TravelogueEditPage.tsx +++ b/frontend/src/components/pages/travelogueEdit/TravelogueEditPage.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from "react"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { usePostUploadImages } from "@queries/index"; import { useGetTravelogue } from "@queries/useGetTravelogue"; @@ -32,7 +32,6 @@ import { ERROR_MESSAGE_MAP } from "@constants/errorMessage"; import { FORM_VALIDATIONS_MAP } from "@constants/formValidation"; import { ROUTE_PATHS_MAP } from "@constants/route"; -import { extractID } from "@utils/extractId"; import resizeAndConvertImage from "@utils/resizeAndConvertImage"; import * as S from "./TravelogueEditPage.styled"; @@ -40,8 +39,7 @@ import * as S from "./TravelogueEditPage.styled"; const TravelogueEditPage = () => { const navigate = useNavigate(); - const location = useLocation(); - const id = extractID(location.pathname); + const { id = "" } = useParams(); const { data } = useGetTravelogue(id); @@ -115,9 +113,9 @@ const TravelogueEditPage = () => { id: Number(id), }, { - onSuccess: (data) => { + onSuccess: () => { handleCloseBottomSheet(); - navigate(ROUTE_PATHS_MAP.travelogue(data?.data?.id)); + navigate(ROUTE_PATHS_MAP.travelogue(id)); }, }, ); diff --git a/frontend/src/components/pages/travelogueRegister/TravelogueRegisterPage.tsx b/frontend/src/components/pages/travelogueRegister/TravelogueRegisterPage.tsx index b3d44bc1..2e2127ae 100644 --- a/frontend/src/components/pages/travelogueRegister/TravelogueRegisterPage.tsx +++ b/frontend/src/components/pages/travelogueRegister/TravelogueRegisterPage.tsx @@ -32,6 +32,7 @@ import { ERROR_MESSAGE_MAP } from "@constants/errorMessage"; import { FORM_VALIDATIONS_MAP } from "@constants/formValidation"; import { ROUTE_PATHS_MAP } from "@constants/route"; +import { extractLastPath } from "@utils/extractId"; import getInitialTravelTitle from "@utils/getInitialTravelTitle"; import resizeAndConvertImage from "@utils/resizeAndConvertImage"; @@ -116,9 +117,11 @@ const TravelogueRegisterPage = () => { days: travelogueDays, }, { - onSuccess: (data) => { + onSuccess: ({ headers: { location } }) => { + const id = extractLastPath(location); + handleCloseBottomSheet(); - navigate(ROUTE_PATHS_MAP.travelogue(data?.data?.id)); + navigate(ROUTE_PATHS_MAP.travelogue(id)); }, }, ); diff --git a/frontend/src/hooks/pages/useTravelPlanDays.ts b/frontend/src/hooks/pages/useTravelPlanDays.ts index b85a5516..6e2a297e 100644 --- a/frontend/src/hooks/pages/useTravelPlanDays.ts +++ b/frontend/src/hooks/pages/useTravelPlanDays.ts @@ -111,7 +111,7 @@ export const useTravelPlanDays = (days: TravelTransformPlaces[]) => { const travelPlanPlace = previousTravelPlanDays[dayIndex]?.places[placeIndex]; if (travelPlanPlace) { - travelPlanPlace.todos?.push({ id: uuidv4(), content: "", checked: false }); + travelPlanPlace.todos?.push({ id: uuidv4(), content: "", isChecked: false }); } }); }, diff --git a/frontend/src/mocks/data/travelPlan.json b/frontend/src/mocks/data/travelPlan.json index fe336226..5028711d 100644 --- a/frontend/src/mocks/data/travelPlan.json +++ b/frontend/src/mocks/data/travelPlan.json @@ -21,13 +21,13 @@ "id": 0, "content": "입장권 구매", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "해설사 예약", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -43,13 +43,13 @@ "id": 0, "content": "한복 대여", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "전통찻집 방문", "order": 1, - "checked": false + "isChecked": false } ] } @@ -71,13 +71,13 @@ "id": 0, "content": "전망대 티켓 구매", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "사랑의 자물쇠 걸기", "order": 1, - "checked": true + "isChecked": true } ] }, @@ -93,13 +93,13 @@ "id": 0, "content": "화장품 쇼핑", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "길거리 음식 맛보기", "order": 1, - "checked": false + "isChecked": false } ] } @@ -129,13 +129,13 @@ "id": 0, "content": "비치타월 준비", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "서핑 보드 대여", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -151,13 +151,13 @@ "id": 0, "content": "야경 촬영", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "바다 산책", "order": 1, - "checked": false + "isChecked": false } ] } @@ -179,13 +179,13 @@ "id": 0, "content": "전망대 방문", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "케이블카 타기", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -201,13 +201,13 @@ "id": 0, "content": "회 구매", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "수산물 구경", "order": 1, - "checked": false + "isChecked": false } ] } @@ -237,13 +237,13 @@ "id": 0, "content": "등산 준비물 체크", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "정상에서 사진 촬영", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -259,13 +259,13 @@ "id": 0, "content": "일출 시간 확인", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "드론 촬영 준비", "order": 1, - "checked": false + "isChecked": false } ] } @@ -287,13 +287,13 @@ "id": 0, "content": "폭포 근처에서 사진 촬영", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "산책로 걷기", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -309,13 +309,13 @@ "id": 0, "content": "동굴 입구에서 기념사진 촬영", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "동굴 내부 탐방", "order": 1, - "checked": false + "isChecked": false } ] } @@ -345,13 +345,13 @@ "id": 0, "content": "사찰 입장권 구매", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "석탑 관람", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -367,13 +367,13 @@ "id": 0, "content": "천문대 관람", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "주변 공원 산책", "order": 1, - "checked": true + "isChecked": true } ] } @@ -395,13 +395,13 @@ "id": 0, "content": "신라 유물 관람", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "기념품 구매", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -417,13 +417,13 @@ "id": 0, "content": "불상 참배", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "주변 경관 감상", "order": 1, - "checked": false + "isChecked": false } ] } @@ -453,13 +453,13 @@ "id": 0, "content": "한옥 체험", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "전통 음식 맛보기", "order": 1, - "checked": true + "isChecked": true } ] }, @@ -475,13 +475,13 @@ "id": 0, "content": "왕실 유물 관람", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "기념 사진 촬영", "order": 1, - "checked": true + "isChecked": true } ] } @@ -503,13 +503,13 @@ "id": 0, "content": "동물 구경", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "놀이 기구 타기", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -525,13 +525,13 @@ "id": 0, "content": "비빔밥 맛보기", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "전통 음식 구매", "order": 1, - "checked": false + "isChecked": false } ] } @@ -561,13 +561,13 @@ "id": 0, "content": "입장권 구매", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "해설사 예약", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -583,13 +583,13 @@ "id": 0, "content": "한복 대여", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "전통찻집 방문", "order": 1, - "checked": false + "isChecked": false } ] } @@ -611,13 +611,13 @@ "id": 0, "content": "전망대 티켓 구매", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "사랑의 자물쇠 걸기", "order": 1, - "checked": true + "isChecked": true } ] }, @@ -633,13 +633,13 @@ "id": 0, "content": "화장품 쇼핑", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "길거리 음식 맛보기", "order": 1, - "checked": false + "isChecked": false } ] } @@ -661,13 +661,13 @@ "id": 0, "content": "전통 공예품 구매", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "한식당 예약", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -683,13 +683,13 @@ "id": 0, "content": "궁궐 투어", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "후원 방문", "order": 1, - "checked": true + "isChecked": true } ] } @@ -711,13 +711,13 @@ "id": 0, "content": "한옥 체험", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "전통 공연 관람", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -733,13 +733,13 @@ "id": 0, "content": "글로벌 음식 맛보기", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "쇼핑", "order": 1, - "checked": false + "isChecked": false } ] } @@ -769,13 +769,13 @@ "id": 0, "content": "입장권 구매", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "해설사 예약", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -791,13 +791,13 @@ "id": 0, "content": "한복 대여", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "전통찻집 방문", "order": 1, - "checked": false + "isChecked": false } ] } @@ -819,13 +819,13 @@ "id": 0, "content": "전망대 티켓 구매", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "사랑의 자물쇠 걸기", "order": 1, - "checked": true + "isChecked": true } ] }, @@ -841,13 +841,13 @@ "id": 0, "content": "화장품 쇼핑", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "길거리 음식 맛보기", "order": 1, - "checked": false + "isChecked": false } ] } @@ -869,13 +869,13 @@ "id": 0, "content": "비치타월 준비", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "서핑 보드 대여", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -891,13 +891,13 @@ "id": 0, "content": "야경 촬영", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "바다 산책", "order": 1, - "checked": false + "isChecked": false } ] } @@ -919,13 +919,13 @@ "id": 0, "content": "사찰 입장권 구매", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "석탑 관람", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -941,13 +941,13 @@ "id": 0, "content": "천문대 관람", "order": 0, - "checked": false + "isChecked": false }, { "id": 1, "content": "주변 공원 산책", "order": 1, - "checked": true + "isChecked": true } ] } @@ -969,13 +969,13 @@ "id": 0, "content": "일출 시간 확인", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "드론 촬영 준비", "order": 1, - "checked": false + "isChecked": false } ] }, @@ -991,13 +991,13 @@ "id": 0, "content": "폭포 근처에서 사진 촬영", "order": 0, - "checked": true + "isChecked": true }, { "id": 1, "content": "산책로 걷기", "order": 1, - "checked": false + "isChecked": false } ] } diff --git a/frontend/src/queries/usePatchTravelPlanTodo.ts b/frontend/src/queries/usePatchTravelPlanTodo.ts index f6f99bee..7e973369 100644 --- a/frontend/src/queries/usePatchTravelPlanTodo.ts +++ b/frontend/src/queries/usePatchTravelPlanTodo.ts @@ -13,7 +13,7 @@ import { QUERY_KEYS_MAP } from "@constants/queryKey"; interface PatchTodoParams { todoId: string; - checked: boolean; + isChecked: boolean; } export const usePatchTravelPlanTodo = (travelPlanId: string) => { @@ -24,8 +24,8 @@ export const usePatchTravelPlanTodo = (travelPlanId: string) => { PatchTodoParams, unknown >({ - mutationFn: ({ todoId, checked }) => - authClient.patch(API_ENDPOINT_MAP.todos(todoId), { checked }), + mutationFn: ({ todoId, isChecked }) => + authClient.patch(API_ENDPOINT_MAP.todos(todoId), { isChecked }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: QUERY_KEYS_MAP.travelPlan.detail(travelPlanId), diff --git a/frontend/src/queries/usePostTravelPlan.ts b/frontend/src/queries/usePostTravelPlan.ts index 6fa42108..329c8b0d 100644 --- a/frontend/src/queries/usePostTravelPlan.ts +++ b/frontend/src/queries/usePostTravelPlan.ts @@ -24,22 +24,6 @@ export const usePostTravelPlan = () => { mutationFn: (travelPlan: TravelPlanPayload) => authClient.post(API_ENDPOINT_MAP.travelPlans, { ...travelPlan, - days: travelPlan.days.map((day) => { - return { - ...day, - places: day.places.map((place) => { - return { - ...place, - todos: place.todos?.map((todo) => { - return { - ...todo, - isChecked: todo.checked, - }; - }), - }; - }), - }; - }), }), onSuccess: () => { queryClient.invalidateQueries({ diff --git a/frontend/src/queries/usePutTravelPlan.ts b/frontend/src/queries/usePutTravelPlan.ts index 0b25dece..a401da69 100644 --- a/frontend/src/queries/usePutTravelPlan.ts +++ b/frontend/src/queries/usePutTravelPlan.ts @@ -28,22 +28,6 @@ export const usePutTravelPlan = () => { mutationFn: ({ travelPlan, id }) => authClient.put(API_ENDPOINT_MAP.travelPlanDetail(id), { ...travelPlan, - days: travelPlan.days.map((day) => { - return { - ...day, - places: day.places.map((place) => { - return { - ...place, - todos: place.todos?.map((todo) => { - return { - ...todo, - isChecked: todo.checked, - }; - }), - }; - }), - }; - }), }), onSuccess: () => { queryClient.invalidateQueries({ diff --git a/frontend/src/types/domain/travelPlan.ts b/frontend/src/types/domain/travelPlan.ts index f502281b..08da88bf 100644 --- a/frontend/src/types/domain/travelPlan.ts +++ b/frontend/src/types/domain/travelPlan.ts @@ -4,7 +4,7 @@ export interface TravelPlanTodo { id: number | string; content: string; order?: number; - checked?: boolean; + isChecked?: boolean; } export interface TravelPlanPlace { id: string;