Files
Aislo/M02_MasterTemplete/M02_MyItems_View.ts
T
eomsangdonandClaude Opus 5.5 207be5bd71 feat(840-4): 내 재료 = 재료 DB(M01)에 없는 자재를 등록하는 자리 — 개인관리 › 자재 등록 칸(만들기 · 고치기 · 지우기) · M01 과 같은 이름 · 규격 · 단위 막음 · 단가산출 재료 고르기 「내 재료」 · 값 바꾸면 자동 따라옴
- 서버 `M02_Material_Own`: M01 자재품목과 이름 · 규격 · 단위 같음 = 409(빈칸 · 대소문자 · ㎏ = kg 무시) · 고치기 · 지우기(쓰는 곳 있으면 409 · 밑줄 폴더 보관본 뺌) · 목록 줄마다 쓰는 곳
- 셈 색인: 단가산출 사본 색인 · 사본 모으기 · 빈틈 채우기에 내 재료 줄을 내 기계처럼 얹음 → 개인 층 단가산출은 값 바뀌면 836-2 길로 따라옴 · 프로젝트 층 = 사본 값
- 화면: 개인관리 › 자재 위 「내 재료」 표 + 고침 칸(`M02_MyMaterial_View` · `M02_MyMaterial_Api`) · 아래 「값을 바로 적은 재료」 모아 보기는 읽기 그대로 · 찾아 넣기 재료 탭 M01 위 「내 재료」 묶음(줄 쌓기 개인 층)
- M01 재료를 본떠 값만 바꾼 내 재료를 만드는 길 = 없었음(걷을 것 없음)

낡은 시험 고침: test_m02_material_own 목록 줄에 「쓰는곳」 칸

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

99 lines
4.1 KiB
TypeScript

/* =============================================================================
* M02_MyItems_View.ts
* M02 「내 품목」 모아 보기(PLAN 821-3 · 요구서 796 3 장 · 읽기만) — 좌측 「내 품목」 칸을 펼치면 가운데에 뜸(개인 층).
* 줄 = 그 층 단가산출 줄에 값을 바로 적은 재료(우리 자재에 안 이어진 것 · 서버 `M02_MyMachine_Look.items`)
* 칸 = 이름 · 규격 · 단위 · 값 · 쓰는 단가산출 수 · 같은 이름 수(같은 이름 묶음 = 이름 차례로 붙어 보임)
* 줄 누름 = 아래 쓰는 단가산출 목록 → 누르면 그 단가산출로(고치기는 거기서 · 여기선 저장 없음)
* 위 = 「내 재료」 등록 칸(840-4 · `M02_MyMaterial_View` — 재료 DB 에 없는 자재 등록) · 이 모아 보기는 그 아래 읽기
* ========================================================================== */
import { createDataTable } from "@ui/ui_template_data_table";
import { createInputField, el } from "@ui/ui_template_elements";
import { createFindList } from "@ui/ui_template_find_list";
import { createText } from "@ui/ui_template_text";
import { listMyItems, type MyItem, type Use } from "./M02_MyMachine_Api";
import { buildMyMaterialBlock } from "./M02_MyMaterial_View";
import { mt } from "./M02_MyMachine_Text";
export interface MyItemsViewOptions {
owner: string | null;
/** 그 단가산출 열기(떠남 확인은 부르는 쪽) */
openSk: (use: Use) => void;
}
export function buildMyItemsView(opt: MyItemsViewOptions): HTMLElement {
let rows: MyItem[] = [];
let shown: MyItem[] = [];
const search = createInputField({ type: "search", placeholder: mt("Find") });
const hint = createText("");
const fail = el("div");
const uses = createFindList({ placeholder: mt("Open_Sk") });
uses.root.hidden = true;
const table = createDataTable({
caption: mt("Crumb_Items"),
columns: [
{ key: "이름", label: mt("Name"), width: 200 },
{ key: "규격", label: mt("Spec"), width: 140 },
{ key: "단위", label: mt("Unit"), width: 60 },
{ key: "값", label: mt("Value"), kind: "number", decimals: 2, trim: true, width: 100 },
{ key: "쓰는곳", label: mt("Uses_Count"), kind: "number", decimals: 0, width: 70 },
{ key: "같은이름", label: mt("Same_Name"), kind: "number", decimals: 0, width: 70 },
],
rows: [],
empty: mt("Items_None"),
mergeSame: ["이름"],
onRowClick: (i) => pick(shown[i]),
});
const pick = (item: MyItem | undefined): void => {
if (!item) return;
uses.root.hidden = false;
uses.hint.textContent = `${item.이름} ${item.규격}`.trim();
uses.setRows(
item.쓰는곳.map((u) => ({
key: u.키,
name: u.이름 || u.키,
sub: u.키,
onPick: () => opt.openSk(u),
})),
);
};
const draw = (): void => {
const words = search.input.value.trim().toLowerCase().split(/\s+/).filter(Boolean);
const count = new Map<string, number>();
for (const r of rows) count.set(r.이름, (count.get(r.이름) ?? 0) + 1);
shown = rows.filter((r) => words.every((w) => `${r.이름} ${r.규격}`.toLowerCase().includes(w)));
hint.textContent = rows.length ? `${shown.length} / ${rows.length}` : "";
table.setRows(
shown.map((r) => ({
이름: r.이름,
규격: r.규격,
단위: r.단위,
값: typeof r.값 === "number" ? r.값 : Number(r.값) || null,
쓰는곳: r.쓰는곳.length,
같은이름: count.get(r.이름) ?? 1,
})),
);
};
search.input.addEventListener("input", draw);
void listMyItems(opt.owner)
.then((got) => (rows = got))
.catch((error) =>
fail.replaceChildren(
createText(error instanceof Error ? error.message : mt("Personal_Only"), "error"),
),
)
.finally(draw);
return el("div", {
className: "m02-mymach-view",
attrs: { "data-my-items": "" },
children: [
buildMyMaterialBlock({ owner: opt.owner }),
el("div", { className: "ui-toolbar", children: [search.root, hint] }),
createText(mt("Items_Note"), "muted"),
fail,
table.root,
uses.root,
],
});
}