Files
Aislo/A00_Common/line_stack_machine_sheet_work.ts
T
eomsangdonandClaude Opus 5.5 c8cd98dec1 feat(846-2): 기계 줄 시간당 작업량 화면 — 산출근거 「시간당 작업량」 줄 먼저 · 비목 ÷ 시간당 작업량 · 제어 구역 일당 / 시간당 식 고르기 · 변수 칸 · 기계 보기 작업량 식
- 산출근거: 일당 「시간당 작업량 = 시공량 560 ㎥/일 ÷ (1 대 × 8 시간) = 70 ㎥/시간」 · 시간당 식 = q · K · f · E · cm 값 줄 + 한 층 분수 Q 식 · 비목 줄 「59,020 원/시간 ÷ 70 ㎥/시간 = 843.1 원」(금액 그대로)
- 제어 구역: 「시간당 작업량」 묶음 맨 위 — 방식 고르기(식 없는 기계 = 잠김 + 까닭) · 시간당 = 작업량 틀 변수 칸(고침 · 원래 값) · 덮음 = 기계덮음.<기계>.작업량
- 기계 보기: 왼쪽 작업량 카드(기계 정본 변수) · 오른쪽 풀이 · 서버가 작업량 틀 연결을 실음(M02_MyMachine_Sheet._work)
- 시험: test_846_2_work_view 새로 · test_845_2 GC000088 비목 줄 기대값을 새 꼴로 고침(846-2 표시 변경) · 헬퍼 가짜 DOM 이 진짜 DOM 처럼 요소를 옮김(같은 요소 두 줄 재사용 흠을 잡게)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-16 00:00:35 +09:00

106 lines
4.6 KiB
TypeScript

/* =============================================================================
* line_stack_machine_sheet_work.ts
* 기계 보기 시간당 작업량(PLAN 846-2 · 요구 883 「시간당 작업량 = 기계의 능력 → 기계에 둠」)
* 왼쪽 = 「시간당 작업량」 접이 카드 — 기계 줄 `값.작업량` 식마다 이름 + 변수 칸(기본 = 기계 값 › 식 문서 기본 ·
* 고친 칸 「고침」 + [원래 값] = 처음 줄 값으로) · 고침 = 지금 줄(저장은 부르는 쪽 — M01 기계 상세 · 내 기계)
* 오른쪽 = 시간당 경비 풀이 아래 「시간당 작업량」 — 그 식 풀이(값 줄 + 결과 식 · `hourlyRows` 산출근거와 같음)
* 식 없는 기계 = 「시간당 작업량 식 없는 기계」 · 작업량 틀 · 표 연결 = 기계 보기 서버(`M02_MyMachine_Sheet._work`)
* ========================================================================== */
import { attachCollapsible, createPanelCard } from "@ui/ui_template_collapsible";
import { el } from "@ui/ui_template_elements";
import type { FormulaDoc } from "../common_util/common_util_formula_doc";
import { calcDoc, type DocLinks } from "../common_util/common_util_formula_doc_calc";
import { specsOf, workDefaults, type WorkSpec } from "../common_util/common_util_formula_doc_work";
import type { MachineRow } from "../common_util/common_util_machine_sheet";
import { lt } from "./line_stack_text";
import { workVarRows } from "./line_stack_machine_work";
import { hourlyRows, workTag } from "./line_stack_work";
export interface SheetWorkOpts {
cur: MachineRow;
orig: MachineRow;
ro: boolean;
links: DocLinks;
/** 캐시에 없는 연결 — 뒤에서 서버 */
miss: () => void;
/** 지금 줄을 고친 뒤 */
changed: () => void;
}
const specsOfRow = (row: MachineRow): WorkSpec[] => specsOf(row.값?.작업량);
const docOf = (o: SheetWorkOpts, key: string): FormulaDoc | null => {
try {
return o.links.doc(key) ?? null;
} catch {
o.miss();
return null;
}
};
const note = (text: string): HTMLElement => el("div", { className: "lstk-empty", text });
/** 왼쪽 카드 — `keep` = 접힘 유지 */
export function sheetWorkCard(o: SheetWorkOpts, keep: boolean): HTMLElement {
const card = createPanelCard(lt("Work_Head"), keep);
card.dataset.machineWork = "1";
const specs = specsOfRow(o.cur);
if (!specs.length) card.append(note(lt("Work_None")));
const was = specsOfRow(o.orig);
specs.forEach((spec, i) => {
const tpl = docOf(o, spec.식);
if (!tpl) return void card.append(note(`${spec.식} — ${lt("Work_Wait")}`));
const first = was.find((s) => s.식 === spec.식) ?? null;
const box = el("div", {
className: "lstk-mctl",
children: [
el("div", { className: "lstk-fhead", children: [workTag("시간당", spec.식), el("span", { className: "lstk-hint", text: tpl.이름 ?? spec.식 })] }), // prettier-ignore
...workVarRows({
tpl,
now: workDefaults(tpl, spec),
base: workDefaults(tpl, first),
ro: o.ro,
set: (k, v) => {
const vars = { ...(spec.변수 ?? {}) };
const back = first?.변수?.[k];
if (v !== null) vars[k] = v;
else if (back !== undefined) vars[k] = back;
else delete vars[k];
const list = specsOfRow(o.cur).map((s, j) => (j === i ? { ...s, 변수: vars } : s));
if (!Object.keys(vars).length) delete list[i].변수;
(o.cur.값 ??= {}).작업량 = list;
o.changed();
},
}),
],
});
card.append(box);
});
attachCollapsible(card);
return card;
}
/** 오른쪽 풀이 — 식마다 머리 + 값 줄 + 결과 식 */
export function sheetWorkOut(o: SheetWorkOpts): HTMLElement {
const specs = specsOfRow(o.cur);
const box = el("div", { className: "lstk-msheet-work", attrs: { "data-machine-work-out": "1" } });
box.append(el("strong", { text: lt("Work_Head") }));
if (!specs.length) return (box.append(note(lt("Work_None"))), box);
for (const spec of specs) {
const tpl = docOf(o, spec.식);
if (!tpl) {
box.append(note(`${spec.식} — ${lt("Work_Wait")}`));
continue;
}
const a = calcDoc(tpl, o.links, workDefaults(tpl, spec), [], new Map(), {});
box.append(
el("div", { className: "lstk-work", children: [workTag("시간당", spec.식), el("span", { className: "lstk-hint", text: tpl.이름 ?? spec.식 })] }), // prettier-ignore
...hourlyRows(tpl, a, (p) => o.links.table(p)).map((r) =>
el("div", { className: `lstk-work ${r.cls ?? ""}`.trim(), children: r.h }),
),
);
}
return box;
}