- SK 셈 답 → 공용 상세 줄(logic/M02_Sangeun_Cover_Model.hoView · 정체 차례 · 바탕 줄 그대로 · 더한줄) · 고침 고리 HoEdit → setLineCover(덮개 · 더한줄 · 열린입력 = 배율) - HoEdit 덧칸 more(줄 빼기 · 별도계상) · M02 = 덧줄 율 고침 · 꼬리표 「변경 항목」 · 뺀 줄 띠 = Sangeun_Cover.removedStrip - 시험 계산 · 텍스트 수식 = 바탕 로직 + 덮개 품 · 단가 사본(applyCovers) · 뺀 바탕 줄 글 거름(dropText — 같은 이름 더한줄이 안 받음) - 717-3 openRowSangeun = 줄 모드 상세(mountRowSk) 얇은 모달(Labor_Detail 부름 그대로) · skCoverTable · coverTable · 뿌리 M02_Sangeun_Cover_Model.ts 지움(Labor_Api import 한 줄) - 낡은 시험: test_717_2b(setQty · setPrice → setLineCover · hoView · dropText) · test_717_3(모델 경로 · setCover · priceKey · sheetGroups 걷힘 → cleanPatch · 화면 이음 새 꼴) - 안내 글(M02_SangeunBaseViews) = 덮개 사본 반영 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
133 lines
5.5 KiB
TypeScript
133 lines
5.5 KiB
TypeScript
/* =============================================================================
|
|
* M02_MasterTemplete_Labor_SangeunModal.ts
|
|
* 일위대가 줄 [단가산출 보기] 모달(PLAN 717-3 · 724-1 · 요구서 내역12 4장 4 · 16 · 24 · 내역 16 · 17-2) —
|
|
* 구조물 조합 일위대가 상세(`Labor_Detail`)의 로직 줄 · 단가산출(SK) 참조 줄 하나의 단가산출을 보고 그 일위대가에서만 고침.
|
|
* · 위 = 일위대가 머리(「1 ㎡ 당」) · 이 줄 수량
|
|
* · 몸 = 단가산출 상세 줄 모드(`Labor_RowSk` — 717-2b 보기 넷 · 공용 상세 줄 모달 그 자리 고침)
|
|
* · [적용] = 그 일위대가 줄 칸 `패치 {덮개, 뺀줄, 더한줄}`(M02 변경 항목 · M01 안 바뀜) · 화면 캐시(저장은 페이지 [저장]) ·
|
|
* 적용 안 하고 닫으면 물음
|
|
* · [단가산출로 저장] = 개인 층 새 SK(이름 받음 · `from-line`) · 일위대가가 자기 개인 층이면 그 줄을 새 SK 참조 줄로
|
|
* ========================================================================== */
|
|
|
|
import { createButton, el, showToast } from "@ui/ui_template_elements";
|
|
import { askConfirm, askText, openModal } from "@ui/ui_template_modal";
|
|
import { createText } from "@ui/ui_template_text";
|
|
import { currentLanguageIndex } from "@ui/ui_template_locale";
|
|
import type { LaborRow } from "./M02_MasterTemplete_Labor_Api";
|
|
import { mountRowSk, saveAsSk } from "./M02_MasterTemplete_Labor_RowSk";
|
|
import type { SkScope } from "./M02_MasterTemplete_Sangeun_Cover";
|
|
import type { LinePatch } from "./logic/M02_Sangeun_Cover_Model";
|
|
|
|
const TEXT = {
|
|
Title: ["단가산출", "Unit-price build-up"],
|
|
Qty: ["이 줄 수량", "Line quantity"],
|
|
Apply: ["적용", "Apply"],
|
|
ToSk: ["단가산출로 저장", "Save as unit-price build-up"],
|
|
AskName: ["새 단가산출 이름(내 개인 층)", "New build-up name (my layer)"],
|
|
Saved: ["{k} 저장함(내 개인 층)", "{k} saved (my layer)"],
|
|
Replaced: ["이 줄을 {k} 참조로 바꿈 — [저장]으로 남김", "Line now refers to {k} — press [Save]"],
|
|
Discard: ["적용 안 한 고침이 있음 — 버리고 닫을까?", "Discard unapplied edits?"],
|
|
Close: ["닫기", "Close"],
|
|
ReadOnly: ["읽기만 — 고친 값은 [단가산출로 저장]으로만 남김", "Read only — use [Save as]"],
|
|
} as const satisfies Record<string, readonly [string, string]>;
|
|
const t = (k: keyof typeof TEXT): string => TEXT[k][currentLanguageIndex as 0 | 1] ?? TEXT[k][0];
|
|
|
|
export interface RowSangeunOptions {
|
|
/** 그 일위대가 층(셈 길 · 참조 위 층 검사) */
|
|
scope: SkScope;
|
|
row: LaborRow;
|
|
/** 줄 이름(로직 키 · 이름) */
|
|
title: string;
|
|
/** 일위대가 머리(이름 · 「1 ㎡ 당」) */
|
|
head: string;
|
|
/** 이 줄 지금 수량 글(「수기 5 ㎥」) */
|
|
qty: string;
|
|
/** 줄 결과 단위(분모 · SK 단위 기본) */
|
|
unit: string;
|
|
readOnly: boolean;
|
|
/** [적용] — 그 줄 패치(null = 고침 없음) */
|
|
apply: (patch: LinePatch | null) => void;
|
|
/** [단가산출로 저장] 뒤 그 줄을 새 SK 참조 줄로(없으면 안 바꿈) */
|
|
replace?: (row: LaborRow) => void;
|
|
}
|
|
|
|
export function openRowSangeun(o: RowSangeunOptions): void {
|
|
const info = el("div", {
|
|
className: "m02-std-sheet__body",
|
|
attrs: { "data-sk-head": "" },
|
|
children: [
|
|
createText(o.head, "muted", 14),
|
|
createText(`${o.title} · ${t("Qty")} ${o.qty}`, "muted", 14),
|
|
...(o.readOnly ? [createText(t("ReadOnly"), "hint")] : []),
|
|
],
|
|
});
|
|
const host = el("div", { attrs: { "data-sk-body": "" } });
|
|
// 읽기만이어도 고쳐 볼 수 있음([단가산출로 저장]으로만 남김) — 717-3 그대로
|
|
const sk = mountRowSk(host, {
|
|
row: o.row,
|
|
scope: o.scope,
|
|
title: o.title,
|
|
unit: o.unit,
|
|
readOnly: false,
|
|
});
|
|
/** 지금 패치(고침 없으면 그 줄 원래 패치) */
|
|
const now = (): LinePatch | null => {
|
|
const got = sk.take();
|
|
return got ? got.patch : (o.row.패치 ?? null);
|
|
};
|
|
let close = (): void => {};
|
|
let done = false;
|
|
const applyBtn = createButton({
|
|
label: t("Apply"),
|
|
variant: "filled",
|
|
onClick: () => {
|
|
if (sk.take()) o.apply(now());
|
|
done = true;
|
|
close();
|
|
},
|
|
});
|
|
applyBtn.dataset.skApply = "";
|
|
applyBtn.hidden = o.readOnly;
|
|
const saveBtn = createButton({
|
|
label: t("ToSk"),
|
|
variant: "ghost",
|
|
onClick: async () => {
|
|
const name = (await askText({ message: t("AskName"), value: o.title }))?.trim();
|
|
if (!name) return;
|
|
try {
|
|
const key = await saveAsSk(o.row, now(), name, o.unit);
|
|
showToast(t("Saved").replace("{k}", key), "success");
|
|
if (!o.replace) return;
|
|
o.replace({
|
|
로직: "",
|
|
입력값: {},
|
|
메모: null,
|
|
별칭: null,
|
|
수량: o.row.수량,
|
|
참조: { 층: "personal", 주인: null, 키: key },
|
|
});
|
|
showToast(t("Replaced").replace("{k}", key), "info");
|
|
done = true;
|
|
close();
|
|
} catch (error) {
|
|
showToast(error instanceof Error ? error.message : String(error), "error");
|
|
}
|
|
},
|
|
});
|
|
saveBtn.dataset.skSave = "";
|
|
({ close } = openModal({
|
|
title: `${t("Title")} — ${o.title}`,
|
|
closeLabel: t("Close"),
|
|
width: "1100px",
|
|
wide: true,
|
|
actions: [saveBtn, applyBtn],
|
|
beforeClose: async () => {
|
|
if (!done && sk.take() && !(await askConfirm({ message: t("Discard"), danger: true })))
|
|
return false;
|
|
sk.destroy();
|
|
return true;
|
|
},
|
|
mount: (body) => body.append(info, host),
|
|
}));
|
|
}
|