diff --git a/A00_Common/b_asset_cache.ts b/A00_Common/b_asset_cache.ts index 2650ddd1..a89ac6dc 100644 --- a/A00_Common/b_asset_cache.ts +++ b/A00_Common/b_asset_cache.ts @@ -279,6 +279,14 @@ export function readPreloadTarget(): string | null { /** 준비 화면이 표시할 단계 안내. ratio가 null이면 진행률을 모른다는 뜻이다. */ export type PreloadReporter = (label: string, ratio: number | null) => void; +/** + * 아직 확정된 지표면이 없다는 뜻의 오류 표식. + * + * 고장이 아니라 "분석·확정이 아직 안 끝난 정상 상태"다. 준비 화면이 이 표식을 보고 + * 장애 안내 대신 다음에 할 일(파일 입력)을 안내한다. + */ +export const PRELOAD_NO_SURFACE = "PRELOAD_NO_SURFACE"; + /** 확정된 지표면의 3D 파일과 그 등고선을 보관함에 채운다(준비 화면에서 호출). * * 사용자가 실제로 보는 것은 이 둘이라 이것만 챙긴다 — 포인트클라우드·배수유역은 제외 @@ -293,7 +301,7 @@ export async function preloadSurfaceAssets( ): Promise { report("확정된 지표면을 확인하는 중…", null); const confirmed = await fetchConfirmedSurface(projectId); - if (!confirmed.model_id) throw new Error("확정된 지표면 모델이 없습니다."); + if (!confirmed.model_id) throw new Error(PRELOAD_NO_SURFACE); const smooth = confirmed.smooth ?? false; const interval = confirmed.contour_interval_m ?? 1.0; diff --git a/A00_Common/b_workflow_nav.ts b/A00_Common/b_workflow_nav.ts index 95993b36..f4e9ed71 100644 --- a/A00_Common/b_workflow_nav.ts +++ b/A00_Common/b_workflow_nav.ts @@ -36,8 +36,21 @@ export async function fetchWorkflowState(projectId: string): Promise { markProjectPreloaded(projectId, signature); navigateTo(target); } catch (error) { + // 확정 지표면이 아직 없는 것은 고장이 아니라 순서 문제다 — 장애 안내 대신 할 일을 알린다. + if (error instanceof Error && error.message === PRELOAD_NO_SURFACE) { + showNoSurface(); + return; + } const detail = error instanceof Error ? ` (${error.message})` : ""; showFailure(`${t("B11_Loading_Failed")}${detail}`); } + function showNoSurface(): void { + progress.root.hidden = true; + message.textContent = t("B11_Loading_NoSurface"); + actions.replaceChildren( + createButton({ + label: t("B11_Loading_Btn_FileInput"), + variant: "filled", + onClick: () => navigateTo(ROUTES.B03_FILE_INPUT), + }), + createButton({ + label: t("B11_Loading_Btn_Dashboard"), + variant: "ghost", + onClick: () => navigateTo(ROUTES.B01_ACCOUNT), + }), + ); + } + function showFailure(text: string): void { progress.root.hidden = true; message.textContent = text; diff --git a/ui_template/ui_template_locale_b2.ts b/ui_template/ui_template_locale_b2.ts index 8ec12aa9..a9c80964 100644 --- a/ui_template/ui_template_locale_b2.ts +++ b/ui_template/ui_template_locale_b2.ts @@ -521,6 +521,11 @@ export const ui_locales_b2 = { "자료를 준비하지 못했습니다. 분석 결과나 저장 경로에 문제가 있을 수 있습니다. 담당자에게 연락해 주세요.", "Could not prepare the data. The analysis result or storage path may be broken. Please contact support.", ], + B11_Loading_NoSurface: [ + "아직 확정된 지표면이 없습니다. 필수 파일을 올리면 지표면 분석이 자동으로 진행되고, 끝나면 이 화면이 자료를 준비합니다.", + "No confirmed surface yet. Upload the required files — the surface analysis runs automatically, and this screen prepares the data once it finishes.", + ], + B11_Loading_Btn_FileInput: ["파일 입력 화면으로", "Go to file input"], B11_Loading_Btn_Continue: ["그래도 화면으로 이동", "Continue anyway"], B11_Loading_Btn_Dashboard: ["대시보드로", "Back to dashboard"], B11_Status_Flow_Title: ["결재 진행 상태", "Payment Progress"],