111 lines
3.6 KiB
TypeScript
111 lines
3.6 KiB
TypeScript
/* =============================================================================
|
|
* B06_wf3_ProfileCross_Api_Fetch.ts
|
|
* 3차 워크플로우(종·횡단 생성) API 클라이언트
|
|
*
|
|
* 백엔드 계약 (B06_wf3_ProfileCross_Router.py):
|
|
* POST /api/projects/{project_id}/sections/generate → 종횡단 생성 + DB 기록
|
|
* GET /api/projects/{project_id}/sections/{route_id} → 종단 요약 조회
|
|
* POST /api/projects/{project_id}/sections/{route_id}/confirm → 종횡단 확정
|
|
*
|
|
* 규칙:
|
|
* - 모든 제어 상수는 config_frontend에서 참조 (하드코딩 금지).
|
|
* - 오류 응답 형식 {status:"error", message:"..."}을 Error로 변환.
|
|
* ========================================================================== */
|
|
|
|
import { API_BASE_URL, API_TIMEOUT_MS } from "@config/config_frontend";
|
|
|
|
/** 종횡단 생성 실행 요청 (SectionGenerateRequest) */
|
|
export interface SectionGenerateRequest {
|
|
route_id: number;
|
|
filter_key: string;
|
|
method?: string;
|
|
smooth?: boolean;
|
|
crs?: string | null;
|
|
station_interval_m?: number | null;
|
|
cross_half_width_m?: number | null;
|
|
cross_sample_interval_m?: number | null;
|
|
long_sample_interval_m?: number | null;
|
|
}
|
|
|
|
/** 종횡단 생성 결과 (SectionGenerateResponse) */
|
|
export interface SectionGenerateResponse {
|
|
status: string;
|
|
project_id: string;
|
|
route_id: number;
|
|
longitudinal_id: number;
|
|
cross_section_count: number;
|
|
length_m: number;
|
|
longitudinal_file_path: string;
|
|
}
|
|
|
|
/** 종단 요약 조회 결과 (SectionSummaryResponse) */
|
|
export interface SectionSummaryResponse {
|
|
status: string;
|
|
project_id: string;
|
|
route_id: number;
|
|
longitudinal: Record<string, unknown> | null;
|
|
}
|
|
|
|
/** 종횡단 확정 결과 (SectionConfirmResponse) */
|
|
export interface SectionConfirmResponse {
|
|
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);
|
|
try {
|
|
const response = await fetch(`${API_BASE_URL}${path}`, {
|
|
...init,
|
|
credentials: "include",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
...(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);
|
|
}
|
|
}
|
|
|
|
/** 확정 경로에서 종·횡단을 생성한다 (측점 배열 → 종단 프로필 → 횡단 샘플). */
|
|
export async function generateSections(
|
|
projectId: string,
|
|
request: SectionGenerateRequest,
|
|
): Promise<SectionGenerateResponse> {
|
|
return requestJson<SectionGenerateResponse>(`/projects/${projectId}/sections/generate`, {
|
|
method: "POST",
|
|
body: JSON.stringify(request),
|
|
});
|
|
}
|
|
|
|
/** 경로의 종단면 요약을 조회한다. */
|
|
export async function getSections(
|
|
projectId: string,
|
|
routeId: number,
|
|
): Promise<SectionSummaryResponse> {
|
|
return requestJson<SectionSummaryResponse>(`/projects/${projectId}/sections/${routeId}`, {
|
|
method: "GET",
|
|
});
|
|
}
|
|
|
|
/** 경로의 종·횡단면을 확정한다. */
|
|
export async function confirmSections(
|
|
projectId: string,
|
|
routeId: number,
|
|
): Promise<SectionConfirmResponse> {
|
|
return requestJson<SectionConfirmResponse>(`/projects/${projectId}/sections/${routeId}/confirm`, {
|
|
method: "POST",
|
|
});
|
|
}
|