feat(M02): 컨테이너 안 「불러오는 중」 — 0.3초 넘을 때만 · 실패 = 까닭 + 다시 불러오기 (PLAN 30-6)

- 공용 부품 ui_template_loading(showLoading · loadingError · delayedShow) — 칸 안 작은 회전 표시 + 「불러오는 중...」 · 화면 전체 잠금 아님 · 다른 페이지도 씀
- 붙인 자리 — 좌측 나무(구조물 · 일위대가 · 사람 나무) · 상세 칸(구조물 표 · 도면 · 면적 · 재료) · 조합 목록 · 조합 상세 · 항목 카드
- 공용 글 Common_Load_Failed · Common_Reload
- 시험 test_ui_loading(0.3초 규칙 가짜 시계 · 실패 글 · 붙은 자리)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 20:02:36 +09:00
co-authored by Claude Opus 5.5
parent 71666a8633
commit 25cf716a0d
9 changed files with 233 additions and 6 deletions
@@ -6,6 +6,7 @@
import { setLeaveGuard } from "../A00_Common/router";
import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
import { loadingError, showLoading } from "@ui/ui_template_loading";
import { t as L } from "@ui/ui_template_locale";
import {
readFilled,
@@ -463,6 +464,7 @@ export function createMain(
return empty("");
}
title.textContent = isCombo(next) ? L("M02_KindTable") : (next.label ?? next.name); // 26-7a
const stop = showLoading(host); // 0.3초 넘으면 상세 칸 안에 「불러오는 중」(PLAN 30-6)
try {
const got = await readTemplate(next.layer, next.kind, next.name, next.projectId);
if (mine !== seq) return;
@@ -481,12 +483,15 @@ export function createMain(
const field = NUMBER_FIELD[next.kind];
const number = field && (got.문서 as Record<string, unknown> | null)?.[field];
if (number) title.textContent = `${String(number)} ${next.label ?? next.name}`;
stop();
await mount(shown, next);
} catch (error) {
if (mine !== seq) return;
empty("");
stop();
const why = error instanceof Error ? error.message : "";
showToast(L("M02_LoadFailed").replace("{value}", why), "error");
host.replaceChildren(loadingError(why, () => void open(next))); // 그 자리에 까닭 + 다시 불러오기
} finally {
stop();
}
}