- B09_wf6_Estimation -> B09_Estimation (폴더·파일·라우트 키/슬러그)
- B07_Quantity_UI_Page.ts 신설: 워크플로우 셸 + 좌측 [확정] 버튼
(renderPendingWorkflow에 leftPanel 옵션 추가로 공용 셸 재사용)
- B07_Quantity_Router.py 신설: POST /api/projects/{id}/quantity/confirm
-> complete_stage(4) 전이만 수행(본문 미구현), main.py 등록
- STAGE_KEYS 재정의: FILE_INPUT/PREPROCESS/PROFILE/SECTION/QUANTITY/DESIGN_DETAIL/ESTIMATION
- 스텝바 라벨·아이콘 4↔5 스왑(수량산출이 4차, 상세설계가 5차), A02 소개 문구 스왑
- 라우터 테이블에 b07-quantity 등록(플레이스홀더 제거), locale 키 5종 추가
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
82 lines
3.2 KiB
TypeScript
82 lines
3.2 KiB
TypeScript
/* =============================================================================
|
|
* B07_Quantity_UI_Page.ts
|
|
* 로그인 후 07: 4차 워크플로우 (수량 산출)
|
|
*
|
|
* ⚠️ 본문 준비 중 — 워크플로우 셸 + 좌측 [확정] 버튼만 구성.
|
|
* 확정 = 워크플로 stage 4(QUANTITY) 완료 처리 후 B08 상세설계로 이동.
|
|
* 수량 본문(B06 종횡단 기반 산출)은 후속 계획에서 구현한다.
|
|
* ========================================================================== */
|
|
|
|
import { ui_locales, currentLanguageIndex } from "@ui/ui_template_locale";
|
|
import { createButton, showToast } from "@ui/ui_template_elements";
|
|
import { API_BASE_URL, CURRENT_PROJECT_ID_KEY } from "@config/config_frontend";
|
|
import { renderPendingWorkflow, workflowSteps } from "../A00_Common/b_page_scaffold";
|
|
import { goToWorkflowStage, WORKFLOW_STEP_ROUTES } from "../A00_Common/b_workflow_nav";
|
|
|
|
/** locale 헬퍼 */
|
|
function L(key: keyof typeof ui_locales): string {
|
|
return ui_locales[key][currentLanguageIndex];
|
|
}
|
|
|
|
/** stage 4(QUANTITY) 완료 요청 — 본문 미구현 상태의 유일한 백엔드 연동. */
|
|
async function confirmQuantityStage(projectId: string): Promise<void> {
|
|
const response = await fetch(
|
|
`${API_BASE_URL}/projects/${encodeURIComponent(projectId)}/quantity/confirm`,
|
|
{ method: "POST", credentials: "include" },
|
|
);
|
|
if (!response.ok) {
|
|
throw new Error(`quantity confirm failed: ${response.status}`);
|
|
}
|
|
}
|
|
|
|
/** 좌측 패널: 준비 중 안내 + 하단 [확정] 액션 행 (다른 워크플로우 페이지와 동일 배치). */
|
|
function buildQuantitySidePanel(projectId: string | null): HTMLElement {
|
|
const panel = document.createElement("div");
|
|
panel.className = "b07-quantity__panel";
|
|
|
|
const note = document.createElement("p");
|
|
note.className = "b07-quantity__pending-note";
|
|
note.textContent = L("B07_Quantity_Side_Pending");
|
|
panel.append(note);
|
|
|
|
const confirmButton = createButton({
|
|
label: L("B07_Quantity_Btn_Confirm"),
|
|
variant: "filled",
|
|
onClick: () => {
|
|
if (!projectId) {
|
|
showToast(L("B07_Quantity_Confirm_Failed"), "error");
|
|
return;
|
|
}
|
|
confirmButton.disabled = true;
|
|
confirmQuantityStage(projectId)
|
|
.then(() => {
|
|
showToast(L("B07_Quantity_Confirm_Success"), "success");
|
|
goToWorkflowStage(projectId, WORKFLOW_STEP_ROUTES[5]);
|
|
})
|
|
.catch(() => {
|
|
showToast(L("B07_Quantity_Confirm_Failed"), "error");
|
|
confirmButton.disabled = false;
|
|
});
|
|
},
|
|
});
|
|
|
|
const actions = document.createElement("div");
|
|
actions.className = "b07-quantity__actions ui-sidebar-actions";
|
|
actions.append(confirmButton);
|
|
panel.append(actions);
|
|
return panel;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* 페이지 진입점
|
|
* -------------------------------------------------------------------------- */
|
|
export async function renderB07Quantity(root: HTMLElement): Promise<void> {
|
|
const projectId = localStorage.getItem(CURRENT_PROJECT_ID_KEY);
|
|
await renderPendingWorkflow(root, {
|
|
title: L("B07_Quantity_Title"),
|
|
steps: workflowSteps(),
|
|
activeStep: 4,
|
|
leftPanel: buildQuantitySidePanel(projectId),
|
|
});
|
|
}
|