260706_0_회사싱크 후 커밋
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
/* =============================================================================
|
||||
* B05_wf2_Route_Api_Fetch.ts
|
||||
* 2차 워크플로우(경로 설계) API 클라이언트
|
||||
*
|
||||
* 백엔드 계약 (B05_wf2_Route_Router.py):
|
||||
* POST /api/projects/{project_id}/route/solve → 경로 탐색 + DB 기록
|
||||
* POST /api/projects/{project_id}/route/confirm → 최신 경로 확정
|
||||
*
|
||||
* 규칙:
|
||||
* - 모든 제어 상수는 config_frontend에서 참조 (하드코딩 금지).
|
||||
* - 오류 응답 형식 {status:"error", message:"..."}을 Error로 변환.
|
||||
* ========================================================================== */
|
||||
|
||||
import { API_BASE_URL, API_TIMEOUT_MS, AUTH_TOKEN_KEY } from "@config/config_frontend";
|
||||
|
||||
/** 경로 제어점 (BP/EP/CP) */
|
||||
export interface RoutePoint {
|
||||
x: number;
|
||||
y: number;
|
||||
order?: number;
|
||||
}
|
||||
|
||||
/** 경로 탐색 실행 요청 (RouteSolveRequest) */
|
||||
export interface RouteSolveRequest {
|
||||
filter_key: string;
|
||||
method?: string;
|
||||
smooth?: boolean;
|
||||
surface_model_id?: number | null;
|
||||
algorithm?: string;
|
||||
bp: RoutePoint;
|
||||
ep: RoutePoint;
|
||||
cp?: RoutePoint[];
|
||||
grade_class?: string;
|
||||
min_curve_radius_m?: number | null;
|
||||
max_uphill_grade?: number | null;
|
||||
max_downhill_grade?: number | null;
|
||||
}
|
||||
|
||||
/** 경로 탐색 실행 결과 (RouteSolveResponse) */
|
||||
export interface RouteSolveResponse {
|
||||
status: string;
|
||||
project_id: string;
|
||||
route_id: number;
|
||||
total_length_m: number;
|
||||
metrics: Record<string, unknown>;
|
||||
required_points_ok: boolean;
|
||||
route_data_path: string;
|
||||
}
|
||||
|
||||
/** 경로 확정 결과 (RouteConfirmResponse) */
|
||||
export interface RouteConfirmResponse {
|
||||
status: string;
|
||||
project_id: string;
|
||||
route_id: number;
|
||||
confirmed: boolean;
|
||||
}
|
||||
|
||||
/** 공통 fetch 헬퍼: 타임아웃 + 인증 헤더 + 오류 응답 변환. */
|
||||
async function requestJson<T>(path: string, init: RequestInit): Promise<T> {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = window.setTimeout(() => controller.abort(), API_TIMEOUT_MS);
|
||||
const token = localStorage.getItem(AUTH_TOKEN_KEY);
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}${path}`, {
|
||||
...init,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
...(init.headers ?? {}),
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
const payload = (await response.json()) as T & { message?: string };
|
||||
if (!response.ok) {
|
||||
throw new Error(payload.message ?? `HTTP ${response.status}`);
|
||||
}
|
||||
return payload;
|
||||
} finally {
|
||||
window.clearTimeout(timeoutId);
|
||||
}
|
||||
}
|
||||
|
||||
/** 경로 탐색을 실행한다 (비용면 생성 → Dijkstra/ridge-valley → GeoJSON 저장). */
|
||||
export async function solveRoute(
|
||||
projectId: string,
|
||||
request: RouteSolveRequest,
|
||||
): Promise<RouteSolveResponse> {
|
||||
return requestJson<RouteSolveResponse>(`/projects/${projectId}/route/solve`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
}
|
||||
|
||||
/** 프로젝트의 최신 경로를 확정한다. */
|
||||
export async function confirmRoute(projectId: string): Promise<RouteConfirmResponse> {
|
||||
return requestJson<RouteConfirmResponse>(`/projects/${projectId}/route/confirm`, {
|
||||
method: "POST",
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user