- 조합 상세 · 카드 · 서고 모두 Labor_Table 한 부품 — 조합 전용 칸(면적 잇기 · 수량산출 모달 · 규격 열 · 다이어그램)은 새 Labor_Combo - 단가산출(SK) 참조 줄 누름 = 새 Labor_SkEdit — 그 SK 문서를 단가산출 상세 부품(수식 탭 첫 화면)으로 열고 [저장] = 수식 저장 → SK 문서 저장 → 일위대가 금액 다시 셈 · 위 층 SK = 읽기만 · 두 번 눌러도 모달 하나 - 옛 조합 전용 표 · 단가산출 보기 모달(Labor_SangeunModal) 지움 · 전국 자재 줄은 Labor_Table 이 그림 - 새 시험 test_806_1_labor_view · 소스 지킴 시험 12 개를 새 자리(Labor_Table · Labor_RowModal · Labor_SkEdit)로 고침 — 옛 Detail 자리 문구가 없어져 낡았음 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
119 lines
4.7 KiB
TypeScript
119 lines
4.7 KiB
TypeScript
/* =============================================================================
|
|
* M02_MasterTemplete_Labor_SkEdit.ts
|
|
* 일위대가 단가산출(SK) 참조 줄 모달(PLAN 806-1 · 요구 698-2 · 689) — 일위대가 표(컨테이너 · 구조물 조합 한 부품)에서
|
|
* 단가산출 줄을 고르면 그 단가산출 문서를 그대로 엶 = M02 단가산출 상세(`Sangeun_Detail` · 첫 탭 「수식」 줄 쌓기) 부품 그대로.
|
|
* · [저장] = 수식 저장(`flush`) → 그 SK 문서 저장(`saveTemplate` · 그 층 · 그 주인) → 닫음 → 부르는 쪽이 일위대가 금액을 다시 셈
|
|
* · 그 층을 못 고치면(위 층 · 남의 주인) 읽기만 · [저장] 없음 · 고친 것 있이 닫으면 물음(버리면 수식 캐시도 비움)
|
|
* 짝 모달 = `Labor_RefEdit`(일위조합 SC 줄).
|
|
* ========================================================================== */
|
|
|
|
import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
|
|
import { openModal } from "@ui/ui_template_modal";
|
|
import { createText } from "@ui/ui_template_text";
|
|
import { readTemplate, saveTemplate, type Layer } from "./M02_MasterTemplete_Api_Fetch";
|
|
import type { LaborRef } from "./M02_MasterTemplete_Labor_Calc";
|
|
import { tc } from "./M02_MasterTemplete_Labor_Text";
|
|
import { mountSangeunDetail } from "./M02_MasterTemplete_Sangeun_Detail";
|
|
|
|
export interface SkEditOptions {
|
|
ref: LaborRef;
|
|
/** 「뒷채움돌 … 」 */
|
|
title: string;
|
|
/** 일위대가 머리(이름 · 「1 ㎡ 당」) */
|
|
head: string;
|
|
readOnly: boolean;
|
|
/** 닫힘 — `saved` = 그 SK 문서를 저장함(부르는 쪽이 금액을 다시 셈) */
|
|
closed: (saved: boolean) => void;
|
|
}
|
|
|
|
/** 단가산출 줄인가 — SK 참조 줄만 이 모달(로직 줄 · SC 줄 · 고정 줄은 다른 길) */
|
|
export const isSkRef = (ref: LaborRef | undefined): ref is LaborRef =>
|
|
!!ref && ref.키.startsWith("SK-");
|
|
|
|
/** 열린 단가산출 모달 — 같은 줄을 빨리 두 번 눌러도 하나만(읽는 동안 늦게 열림) */
|
|
const opened = new Set<string>();
|
|
|
|
export async function openSkEdit(opt: SkEditOptions): Promise<void> {
|
|
const layer = opt.ref.층 as Layer;
|
|
const at = `${layer}/${opt.ref.주인 ?? ""}/${opt.ref.키}`;
|
|
if (opened.has(at)) return;
|
|
opened.add(at);
|
|
let doc: unknown;
|
|
let version: string;
|
|
try {
|
|
const got = await readTemplate(layer, "sangeun", opt.ref.키, null, opt.ref.주인);
|
|
doc = got.문서;
|
|
version = got.판 ?? "";
|
|
} catch (error) {
|
|
opened.delete(at);
|
|
return void showToast(error instanceof Error ? error.message : tc("Load_Failed"), "error");
|
|
}
|
|
let dirty = false;
|
|
let saved = false;
|
|
let handle: ReturnType<typeof mountSangeunDetail> | null = null;
|
|
const finish = (): void => {
|
|
handle?.destroy(); // 고친 채 버리면 수식 캐시도 비움
|
|
opened.delete(at);
|
|
opt.closed(saved);
|
|
};
|
|
openModal({
|
|
title: opt.title,
|
|
closeLabel: tc("In_Close"),
|
|
dialogClass: "m02-modal m02-labsk",
|
|
width: "1100px",
|
|
wide: true,
|
|
beforeClose: async () => {
|
|
if (dirty && !saved && !(await showConfirmDialog(tc("Ref_Discard")))) return false;
|
|
finish();
|
|
return true;
|
|
},
|
|
mount: (body, close, head) => {
|
|
const host = el("div", { attrs: { "data-labor-sk": opt.ref.키 } });
|
|
handle = mountSangeunDetail(host, doc, {
|
|
layer,
|
|
owner: opt.ref.주인,
|
|
readOnly: opt.readOnly,
|
|
onChanged: (d) => (dirty = d && !opt.readOnly),
|
|
onVersion: (v) => (version = v), // 수식 저장이 파일 판을 바꿈 — 문서 저장이 이어 받음
|
|
source: true, // 페이지와 같은 길 — 수식 저장 단추는 이 [저장] 한 번에 모임
|
|
});
|
|
const ok = createButton({
|
|
label: tc("Save"),
|
|
variant: "filled",
|
|
onClick: () =>
|
|
void (async () => {
|
|
if (!handle) return;
|
|
try {
|
|
await handle.flush();
|
|
await saveTemplate(
|
|
layer,
|
|
"sangeun",
|
|
opt.ref.키,
|
|
null,
|
|
version,
|
|
handle.getDoc(),
|
|
opt.ref.주인,
|
|
);
|
|
saved = true;
|
|
showToast(tc("Saved"), "success");
|
|
close();
|
|
finish();
|
|
} catch (error) {
|
|
showToast(error instanceof Error ? error.message : tc("Lib_SaveFailed"), "error");
|
|
}
|
|
})(),
|
|
});
|
|
ok.dataset.skSave = "";
|
|
body.append(
|
|
createText(opt.head, "muted", 14),
|
|
createText(
|
|
opt.readOnly ? `${tc("Ref_Shared")} · ${tc("Ref_ReadOnly")}` : tc("Ref_Shared"),
|
|
"hint",
|
|
),
|
|
host,
|
|
);
|
|
if (!opt.readOnly) head.append(ok); // [저장] = 머리 [닫기] 왼쪽
|
|
},
|
|
});
|
|
}
|