/* ============================================================================= * M02_MasterTemplete_Labor_RefEdit.ts * 일위대가 참조 줄 모달(51-14) — 서고 원본(50-3)을 그 자리에서 고침 · [저장] = 서고 저장 길(`saveTemplate`) · * 그 문서를 쓰는 모든 구조물에 따라감(머리 한 줄 알림) · 그 층을 못 고치면 읽기만. * · 단가승격 [옵션] = 승격 문서 로직 한 줄의 넣을 값 모달(`Labor_Input`) * · 일위조합 [수정] = 사전조합 상세(서고 모드 표 · 안 줄 [옵션] · 수량 · 위로 · 아래로 · 삭제 · 추가) * 닫으면(저장 · 취소 모두) `closed` — 부르는 쪽이 구조물 일위대가 표를 다시 셈. * ========================================================================== */ import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements"; import { openModal } from "@ui/ui_template_modal"; import { readTemplate, saveTemplate, type Layer } from "./M02_MasterTemplete_Api_Fetch"; import { fetchLogicInputs, type LaborRow } from "./M02_MasterTemplete_Labor_Api"; import type { LaborRef } from "./M02_MasterTemplete_Labor_Calc"; import { openLaborInput } from "./M02_MasterTemplete_Labor_Input"; import { tc } from "./M02_MasterTemplete_Labor_Text"; import { keepKnown } from "./M02_Labor_Values_Model"; export interface RefEditOptions { ref: LaborRef; /** 「SP-000001 메쌓기」 */ title: string; readOnly: boolean; closed: () => void; } const fail = (error: unknown, key: "Load_Failed" | "Lib_SaveFailed"): void => showToast(error instanceof Error ? error.message : tc(key), "error"); export async function openRefEdit(opt: RefEditOptions): Promise { const kind = opt.ref.키.startsWith("SP-") ? "promote" : "precombo"; const layer = opt.ref.층 as Layer; let doc: { 담은로직?: LaborRow[] }; let 판: string; try { const got = await readTemplate(layer, kind, opt.ref.키, null); doc = got.문서 as typeof doc; 판 = got.판 ?? ""; } catch (error) { return fail(error, "Load_Failed"); } const save = (body: unknown): Promise => saveTemplate(layer, kind, opt.ref.키, null, 판, body).then(() => showToast(tc("Saved"), "success"), ); const notice = opt.readOnly ? `${tc("Ref_Shared")} · ${tc("Ref_ReadOnly")}` : tc("Ref_Shared"); if (kind === "promote") { const row = doc.담은로직?.[0]; if (!row) return fail(null, "Load_Failed"); const logic = row.로직 ? ((await fetchLogicInputs([row.로직]).catch(() => null))?.로직[0] ?? null) : null; return openLaborInput({ title: opt.title, logic, values: row.입력값, memo: row.메모, readOnly: opt.readOnly, notice, okLabel: tc("Save"), done: (next) => { row.입력값 = logic ? keepKnown(logic.입력, next.입력값).kept : next.입력값; row.메모 = next.메모; void save(doc) .catch((error) => fail(error, "Lib_SaveFailed")) .finally(opt.closed); }, }); } // 사전조합 — 상세와 같은 부품(서로 부르므로 늦게 받음) const { mountLaborDetail } = await import("./M02_MasterTemplete_Labor_Detail"); let dirty = false; let handle: ReturnType | null = null; const finish = (): void => { handle?.destroy(); opt.closed(); }; openModal({ title: opt.title, closeLabel: tc("In_Close"), dialogClass: "m02-modal m02-labref", beforeClose: async () => { if (dirty && !(await showConfirmDialog(tc("Ref_Discard")))) return false; finish(); return true; }, mount: (body, close) => { const host = el("div", { attrs: { "data-labor-ref": opt.ref.키 } }); handle = mountLaborDetail(host, doc, { layer, column: opt.ref.키, readOnly: opt.readOnly, onChanged: (d) => (dirty = d && !opt.readOnly), goArea: null, mode: "precombo", }); const cancel = createButton({ label: tc(opt.readOnly ? "In_Close" : "In_Cancel"), variant: "ghost", onClick: async () => { if (dirty && !(await showConfirmDialog(tc("Ref_Discard")))) return; close(); finish(); }, }); const ok = createButton({ label: tc("Save"), variant: "filled", onClick: () => void save(handle?.getDoc()).then( () => { close(); finish(); }, (error) => fail(error, "Lib_SaveFailed"), ), }); body.append( el("p", { className: "m02-labin__muted", text: notice, attrs: { "data-labor-notice": "" }, }), host, el("div", { className: "m02-labin__foot", children: opt.readOnly ? [cancel] : [cancel, ok], }), ); }, }); }