Merge remote-tracking branch 'origin/main_laptop_1' into sub_laptop_1

This commit is contained in:
2026-10-01 10:06:44 +09:00
2 changed files with 45 additions and 7 deletions
+38 -2
View File
@@ -23,6 +23,8 @@ import {
type PickResult,
} from "./M01_EasyCalc_Model";
import { openEasyPick } from "./M01_EasyCalc_Pick";
import { openEasyCond, readCond } from "./M01_EasyCalc_Cond";
import { openEasyTable, readFinds } from "./M01_EasyCalc_Table";
import "./M01_EasyCalc_Cards.css";
const TEXT = {
@@ -60,6 +62,8 @@ const TEXT = {
Auto: ["자동", "auto"],
Locked: ["잠김", "Locked"],
ToNumber: ["숫자로 바꾸기", "Make it a number"],
ByTable: ["표 보고 고르기", "Choose from table"],
ByCond: ["조건 보고 고치기", "Edit conditions"],
ToNumber_Wait: ["계산이 끝난 뒤 가능", "Available after calculation"],
ToNumber_Ask: [
"자동 값을 그대로 숫자로 바꿈 · 이후 자동으로 달라지지 않음",
@@ -92,7 +96,7 @@ interface Ctx {
doc: EasyDoc;
lines: Map<string, CalcLine>;
readOnly: boolean;
on: { change(doc: EasyDoc): void };
on: { change(doc: EasyDoc): void; trial?(): Record<string, unknown> };
/** 숫자 아님으로 친 글 — 다시 그려도 칸에 남김 */
badText: Map<string, string>;
}
@@ -205,6 +209,22 @@ async function lockToNumber(ctx: Ctx, card: EasyCard, value: number): Promise<vo
}
}
/** 표 · 조건 창 — 답(새 식)이 있으면 그 카드 식만 바꿈 */
async function editFormula(
ctx: Ctx,
card: EasyCard,
open: typeof openEasyTable | typeof openEasyCond,
): Promise<void> {
if (picking) return;
picking = true;
try {
const formula = await open(card, ctx.doc, ctx.on.trial?.());
if (formula !== null) patchCard(ctx, card, { qtyFormula: formula });
} finally {
picking = false;
}
}
/* ------------------------------ 칸 만들기 ------------------------------ */
const text = (cls: string, value: string): HTMLSpanElement =>
@@ -414,6 +434,22 @@ function lockedNote(ctx: Ctx, card: EasyCard): HTMLElement {
});
if (!line) button.title = tc("ToNumber_Wait");
note.push(button);
const formula = card.qtyFormula;
const tools: [boolean, keyof typeof TEXT, typeof openEasyTable | typeof openEasyCond][] = [
[formula !== null && !!readFinds(formula)?.length, "ByTable", openEasyTable],
[formula !== null && !!readCond(formula, ctx.doc.row), "ByCond", openEasyCond],
];
for (const [has, label, open] of tools) {
if (has)
note.push(
createButton({
label: tc(label),
variant: "ghost",
size: "sm",
onClick: () => void editFormula(ctx, card, open),
}),
);
}
}
return el("div", { className: "m01-easycards-locknote", children: note });
}
@@ -485,7 +521,7 @@ export function renderCards(
host: HTMLElement,
doc: EasyDoc,
ans: CalcAnswer | null,
on: { change(doc: EasyDoc): void },
on: { change(doc: EasyDoc): void; trial?(): Record<string, unknown> },
): void {
const badText = badTexts.get(host) ?? new Map<string, string>();
badTexts.set(host, badText);
+7 -5
View File
@@ -15,12 +15,14 @@ import {
} from "@ui/ui_template_elements";
import { openModal } from "@ui/ui_template_modal";
import { fetchPick, fetchSubs, type SubInfo } from "../M01_MasterData_Api_Fetch";
import { fetchMaterials } from "../M01_MasterData_UI_Logic_Api";
import { fetchMaterials, type ElementBrief } from "../M01_MasterData_UI_Logic_Api";
import { listEasy, listMachines, machineElement, plainError } from "./M01_EasyCalc_Api";
import type { PickResult } from "./M01_EasyCalc_Model";
import "./M01_EasyCalc_Pick.css";
type Kind = PickResult["kind"];
/** 후보 줄 — 서버는 구분 · 상세구분도 주지만 ElementBrief 타입에는 없음 */
type Brief = ElementBrief & { 구분?: string; 상세구분?: string };
const TEXT = {
Title: ["넣을 것 고르기", "Pick what to add"],
@@ -136,13 +138,13 @@ const SOURCES: Partial<Record<Kind, Source>> = {
? await fetchPick("price", f.q).then((r) => ({
total: r.total,
items: r.items
.filter((it) => !f.sub || (it as { 구분?: string }).구분 === f.sub)
.map((it) => ({ ...it, 구분: (it as { 구분?: string }).구분, 상세구분: undefined })),
.filter((it) => !f.sub || (it as Brief).구분 === f.sub)
.map((it) => ({ ...it, 구분: (it as Brief).구분 })),
}))
: await fetchMaterials({ sub: f.sub, ...(f.detail ? { detail: f.detail } : {}) }).then(
(r) => ({
total: r.total,
items: r.items.map((it) => ({ ...it, 구분: it.구분 ?? f.sub })),
items: r.items.map((it) => ({ ...it, 구분: (it as Brief).구분 ?? f.sub })),
}),
);
return {
@@ -153,7 +155,7 @@ const SOURCES: Partial<Record<Kind, Source>> = {
const unit = typeof it.단위 === "string" ? it.단위 : "";
const price = num(it.값);
const element: Record<string, string> = { 구분: it.구분 ?? f.sub };
const detail = (it as { 상세구분?: string }).상세구분;
const detail = (it as Brief).상세구분;
if (detail) element["상세구분"] = detail;
element["검색어"] = `${name} ${spec}`.trim();
return {