+
+
+
+ {quotationDetail.isConfirmed !== false && (
+
+ )}
+
+ {quotationDetail.isAssigned !== false && (
+
+ )}
-
-
-
- {quotationDetail.maker.nickName}
-
-
-
-
-
{quotationDetail.maker.averageRating}
-
- ({quotationDetail.maker.totalReviews})
-
-
-
ㅣ
-
-
ㅣ
-
-
{quotationDetail.maker.totalConfirms}
-
확정
-
-
-
-
+
+
-
{quotationDetail.maker.totalFollows}
+
+
+
+
+ {quotationDetail.maker.nickName}
+
+
+
+
+
{quotationDetail.maker.averageRating}
+
+ ({quotationDetail.maker.totalReviews})
+
+
+
ㅣ
+
+
ㅣ
+
+
{quotationDetail.maker.totalConfirms}
+
확정
+
+
+
+
+
+
{quotationDetail.maker.totalFollows}
+
-
-
-
- {quotationDetail.content}
-
+
+
+ {quotationDetail.content}
+
+
-
-
-
-
- 견적 코코넛
-
-
- {quotationDetail.price} 개
-
-
-
-
-
플랜 공유하기
-
{sharePromptContent}
-
-
-
-
- 플랜 정보
-
-
- {planDetail.status === "PENDING" && (
-
-
-
확정하지 않은 플랜이에요!
+
+
+
+ 견적 코코넛
+
+
+ {quotationDetail.price} 개
+
+
+
+
+
플랜 공유하기
+
{sharePromptContent}
+
+
+
+
+ 플랜 정보
+
+
+ {planDetail.status === "PENDING" && (
+
-
- )}
+ )}
+
-
-
- {planDetail.status === "PENDING" && (
-
-
+ {isModalOpen && (
+
setIsModalOpen(false)}>
+
+
+
+
보유 코코넛 :
{coconut}
{" "}
+
개
+
+
+
필요 코코넛 :
+
+ {quotationDetail.price.toLocaleString()}
+
+
개
+
+
+
+
+ )}
);
}
diff --git a/src/services/planService.ts b/src/services/planService.ts
index 2662cad..7e6a681 100644
--- a/src/services/planService.ts
+++ b/src/services/planService.ts
@@ -1,4 +1,4 @@
-import { BAD_REQUEST, CONFLICT } from "@/utils/errorStatus";
+import { BAD_REQUEST, CONFLICT, NOT_FOUND, FORBIDDEN } from "@/utils/errorStatus";
import { api } from "./api";
import { ServiceArea } from "@/utils/formatRegion";
@@ -95,9 +95,8 @@ const planService = {
}
return response;
- } catch (error) {
- console.error("여행 조회 실패", error);
- throw error;
+ } catch (error: any) {
+ throw error("플랜 목록을 불러오는데 실패했습니다.");
}
},
@@ -110,8 +109,7 @@ const planService = {
window.location.href = "/404";
return Promise.reject(new Error("해당 여행 플랜을 찾을 수 없습니다."));
}
- console.error("여행 데이터 요청 실패", error);
- throw error;
+ throw error("여행 데이터를 불러오는데 실패했습니다.");
}
},
@@ -158,8 +156,8 @@ const planService = {
`/plans/dreamer?readyToComplete=true${queryString}`,
);
return response;
- } catch (error) {
- console.error("완료 플랜 조회 실패", error);
+ } catch (error: any) {
+ throw error("완료 플랜을 불러오는데 실패했습니다.");
}
},
@@ -171,8 +169,8 @@ const planService = {
`/plans/dreamer?reviewed=false${queryString}`,
);
return response;
- } catch (error) {
- console.error("리뷰 작성 가능 플랜 조회 실패", error);
+ } catch (error: any) {
+ throw error("리뷰 가능 플랜을 불러오는데 실패했습니다.");
}
},
@@ -180,8 +178,12 @@ const planService = {
try {
const response = await api.delete(`/plans/${planId}`);
return response;
- } catch (error) {
- console.error("플랜 취소 실패", error);
+ } catch (error: any) {
+ if (error.response?.status === BAD_REQUEST) {
+ throw new Error("진행중인 플랜은 삭제할 수 없습니다.");
+ } else if (error.response?.status === FORBIDDEN) {
+ throw new Error("해당 플랜을 삭제할 권한이 없습니다.");
+ }
}
},
@@ -191,20 +193,17 @@ const planService = {
console.log("응답 데이터:", response);
return response;
} catch (error: any) {
- if (error.response) {
+ if (error.response?.status === BAD_REQUEST) {
// 서버에서 응답이 왔을 때 (500, 404 등)
- console.error("Server Error:", error.response.status, error.response.data);
- throw new Error(
- `API Error: ${error.response.status} - ${error.response.data.message || "Unknown error"}`,
- );
+ throw new Error("플랜 완료 요청은 진행중(확정견적이 있는) 상태일 때만 가능합니다.");
+ } else if (error.response?.status === NOT_FOUND) {
+ throw new Error("해당 플랜을 찾을 수 없습니다.");
} else if (error.request) {
// 요청은 갔지만 응답이 없을 때 (네트워크 문제)
- console.error("No Response:", error.request);
- throw new Error("No response from server. Please try again.");
+ throw new Error("서버로부터 응답이 없습니다. 다시 시도해 주세요.");
} else {
// 요청 자체의 문제 (설정 오류 등)
- console.error("Request Error:", error.message);
- throw new Error("Request setup error.");
+ throw new Error("요청 오류 입니다.");
}
}
},
diff --git a/src/services/quotationServiceDreamer.ts b/src/services/quotationServiceDreamer.ts
index 3609eb9..a577d43 100644
--- a/src/services/quotationServiceDreamer.ts
+++ b/src/services/quotationServiceDreamer.ts
@@ -1,3 +1,4 @@
+import { FORBIDDEN } from "@/utils/errorStatus";
import { api } from "./api";
interface MakerInfo {
@@ -57,19 +58,23 @@ export const QuotationServiceDreamer = {
}
return response;
- } catch (error) {
- console.error("견적 목록 조회 실패", error);
- throw error;
+ } catch (error: any) {
+ if (error.response && error.response?.status === FORBIDDEN) {
+ throw new Error("해당 견적서의 Dreamer만 조회할 수 있습니다.");
+ }
+ throw new Error("견적서를 불러 오는 중 오류가 발생했습니다.");
}
},
getQuotationDetail: async (planId: string): Promise
=> {
try {
- const response = await api.get(`/plans/${planId}/qoutes`);
+ const response = await api.get(`/plans/${planId}/quotes`);
return response;
- } catch (error) {
- console.error("견적 상세 조회 실패", error);
- throw error;
+ } catch (error: any) {
+ if (error.response && error.response?.status === FORBIDDEN) {
+ throw new Error("해당 견적서의 Maker와 Dreamer만 조회할 수 있습니다.");
+ }
+ throw new Error("견적서를 불러 오는 중 오류가 발생했습니다.");
}
},
@@ -78,15 +83,8 @@ export const QuotationServiceDreamer = {
const response = await api.patch(`quotes/${quoteId}/confirm`, payload);
return response;
} catch (error: any) {
- if (error.response) {
- // 서버에서 응답이 왔을 때 (500, 404 등)
- throw error.response;
- } else if (error.request) {
- // 요청은 갔지만 응답이 없을 때 (네트워크 문제)
- throw new Error("No response from server. Please try again.");
- } else {
- // 요청 자체의 문제 (설정 오류 등)
- throw new Error("Request setup error.");
+ if (error.response && error.response?.status === FORBIDDEN) {
+ throw new Error("해당 견적서의 Dreamer만 확정할 수 있습니다.");
}
}
},