- 개인 층 재료 고름 = 창 머리 [신규 자재] — 만들어 바로 자재 목록에 넣음(`openNewMaterial`) - 찾아 넣기 창 기계(M01 EQ) 탭 — 「M01 전체」 묶음 안 · 부르는 쪽이 `machine` 을 줄 때만 보임 - 엑셀 연결 = 줄 갈래대로 탭(노임 = 인력 · 기계 = 기계 · 자재 = 재료 · 그 밖 = 기초) — 불러오기 고르기 · 남은 줄 · 못옮김 · 안 이은 줄 연결 모두 같은 창 · 따로 [기계] 단추 걷음 - 낡은 시험 고침(721 · 729-3: 기계 고름 길이 찾아 넣기 창으로 옮김) + 736-2 글 시험 추가 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
105 lines
4.2 KiB
TypeScript
105 lines
4.2 KiB
TypeScript
/* =============================================================================
|
|
* M02_MasterTemplete_Labor_Unlinked.ts
|
|
* 일위대가표 안 이은 줄 띠 · [연결](PLAN 729-3 · 요구서 내역19 1장 8 · 분석 19-B D-2) —
|
|
* · 안 이은 줄 = 고정 줄 중 비율 줄 아님 · 이음(노임 · 자재 · 기계) 모두 빈 것(서버 목록 summary `안이은줄` 과 같은 규칙)
|
|
* · 띠 = 「M01 연결 없음 n 줄(옛 자료)」 · 고칠 수 있으면 [연결] → 줄마다 [찾기](노임 LB · 자재 MT · 721 찾아 넣기 창) ·
|
|
* [기계](M01 기계 EQ) — 고정 줄 이름 · 규격 · 엑셀 숫자(출처)는 그대로 · 이음만 붙임 → 상세 고침(저장은 [저장])
|
|
* 계산은 서버(이음 = 단가 책 값) — 화면은 고름만.
|
|
* ========================================================================== */
|
|
|
|
import { createBanner } from "@ui/ui_template_banner";
|
|
import { createButton, el, showToast } from "@ui/ui_template_elements";
|
|
import { t as L } from "@ui/ui_template_locale";
|
|
import { openModal } from "@ui/ui_template_modal";
|
|
import { createTable } from "@ui/ui_template_table";
|
|
import { getActiveLayer, getActiveOwner } from "./M02_MasterTemplete_Api_Fetch";
|
|
import { openFindPicker } from "./M02_MasterTemplete_Find_Pick";
|
|
import type { LaborDoc } from "./M02_MasterTemplete_Labor_Api";
|
|
import type { LaborFixed } from "./M02_MasterTemplete_Labor_Calc";
|
|
|
|
/** 안 이은 고정 줄 */
|
|
export const unlinkedFixes = (doc: LaborDoc): LaborFixed[] =>
|
|
doc.담은로직
|
|
.map((row) => row.고정)
|
|
.filter(
|
|
(fx): fx is LaborFixed => !!fx && !fx.비율 && !Object.values(fx.이음 ?? {}).some(Boolean),
|
|
);
|
|
|
|
/** 이음 붙임 — 하나만(노임 · 자재 · 기계) */
|
|
const linkTo = (fx: LaborFixed, kind: "노임" | "자재" | "기계", code: string): void => {
|
|
fx.이음 = { 노임: null, 자재: null, 기계: null, [kind]: code };
|
|
};
|
|
|
|
/** [연결] 창 — 줄마다 찾기 · 기계 · 고르면 `changed` */
|
|
function openLink(doc: LaborDoc, changed: () => void): void {
|
|
openModal({
|
|
title: L("M02_GridLinkTitle"),
|
|
closeLabel: L("M02_Close"),
|
|
width: "960px",
|
|
dialogClass: "m02-modal",
|
|
mount: (body) => {
|
|
const draw = (): void => {
|
|
const rows = unlinkedFixes(doc).map((fx) => {
|
|
const done = (kind: "노임" | "자재" | "기계", code: string): void => {
|
|
linkTo(fx, kind, code);
|
|
changed();
|
|
draw();
|
|
};
|
|
const find = createButton({
|
|
label: L("M02_LeftFind"),
|
|
size: 24,
|
|
variant: "ghost",
|
|
onClick: () =>
|
|
openFindPicker({
|
|
layer: getActiveLayer(),
|
|
owner: getActiveOwner(),
|
|
title: `${fx.이름} ${fx.규격 ?? ""}`.trim(),
|
|
logic: () => showToast(L("M02_GridLinkNoLogic"), "info"),
|
|
element: (e) => done(e.종류 === "인력" ? "노임" : "자재", e.코드),
|
|
machine: (e) => done("기계", e.코드), // 736-2 기계도 같은 창 탭
|
|
}),
|
|
});
|
|
return [
|
|
fx.이름,
|
|
fx.규격 ?? "",
|
|
fx.단위 ?? "",
|
|
el("div", { className: "ui-toolbar", children: [find] }),
|
|
];
|
|
});
|
|
body.replaceChildren(
|
|
createTable(
|
|
[
|
|
{ label: L("M02_SangeunColName") },
|
|
{ label: L("M02_LeftSpec") },
|
|
{ label: L("M02_SangeunColUnit"), width: "64px" },
|
|
{ label: L("M02_LeftPick"), width: "180px" },
|
|
],
|
|
rows,
|
|
{ density: "data", empty: L("M02_LeftZero") },
|
|
),
|
|
);
|
|
};
|
|
draw();
|
|
},
|
|
});
|
|
}
|
|
|
|
/** 띠 — 안 이은 줄이 없으면 null · `edit` 있으면 [연결] */
|
|
export function unlinkedBar(
|
|
doc: LaborDoc,
|
|
edit?: ((qtyOnly: boolean) => void) | false,
|
|
): HTMLElement | null {
|
|
const n = unlinkedFixes(doc).length;
|
|
if (!n) return null;
|
|
const go = edit
|
|
? [createButton({ label: L("M02_GridLink"), size: 24, onClick: () => openLink(doc, () => edit(false)) })]
|
|
: []; // prettier-ignore
|
|
const bar = createBanner({
|
|
tone: "warning",
|
|
text: L("M02_GridUnlinked").replace("{n}", String(n)),
|
|
actions: go,
|
|
});
|
|
bar.dataset.laborUnlinked = String(n);
|
|
return bar;
|
|
}
|