feat(M02): 구조물집계표 넷째 카드 「선택 입력」 — 로직마다 입력 목록 · 자리 고르기(면적 · 재료 · 선택 · 안 씀) · 알약 줄에 뜸 (PLAN 25-2c)
- 카드 = 로직 이름 · 결과단위 묶음 아래 입력 줄(이름 · 설명 · 단위 · 고르기/범위 · 자동값 흐리게) + 자리 상자 · 처음은 모두 안 씀 - 저장 = 집계표 [저장]에 이어 PUT input-links(자동저장 없음) · 읽기만 층은 상자 잠금 - 면적 · 재료로 고른 입력은 그 시트 알약 줄에 「로직 이름 · 입력 이름」 · 자재 모드에서도 [목록에서 빼기] 막음(고정) - 알약 줄 시험을 합계 줄 아래 자리에 맞춤(25-0 뒤 어긋난 것) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D2nUMUMTsqm93PbQtipo6c
This commit is contained in:
@@ -42,6 +42,7 @@ import {
|
||||
type DrawingTemplateDoc,
|
||||
type DrawingTemplateHandle,
|
||||
} from "./M02_MasterTemplete_Drawing";
|
||||
import { createInputsCard, inputPills, type InputsCardHandle } from "./M02_MasterTemplete_Inputs";
|
||||
import "./M02_MasterTemplete_Structure.css";
|
||||
|
||||
/** 구조물 도면이 걸리는 집계표 이름 — 서버 `M02_MasterTemplete_Store.STRUCTURE_TABLE` 과 같은 글 */
|
||||
@@ -207,8 +208,12 @@ export async function pillsFor(
|
||||
kind: SheetKind,
|
||||
column: string,
|
||||
): Promise<{ links: LinkOptions; notice?: string }> {
|
||||
if (kind === "material") return { links: { 항목: [], 모드: "자재", 자재찾기: searchMaterials } };
|
||||
const none = (notice: string) => ({ links: { 항목: [], 모드: "입력" as const }, notice });
|
||||
if (kind === "material") {
|
||||
const own = await inputPills(column, "재료");
|
||||
return { links: { 항목: own, 모드: "자재", 자재찾기: searchMaterials } };
|
||||
}
|
||||
const own = await inputPills(column, "면적"); // 선택 입력 카드가 면적산출로 고른 입력
|
||||
const none = (notice: string) => ({ links: { 항목: own, 모드: "입력" as const }, notice });
|
||||
const table = await readTemplate(getActiveLayer(), "table", STRUCTURE_TABLE, null).catch(
|
||||
() => null,
|
||||
);
|
||||
@@ -217,7 +222,7 @@ export async function pillsFor(
|
||||
if (!combo) return none(TEXT.noPrice);
|
||||
try {
|
||||
const got = await fetchComboInputs(combo);
|
||||
const 항목 = got.물량.map((q) => ({ 키: q.키, 이름: q.이름, 단위: q.단위 }));
|
||||
const 항목 = [...got.물량.map((q) => ({ 키: q.키, 이름: q.이름, 단위: q.단위 })), ...own];
|
||||
return 항목.length ? { links: { 항목, 모드: "입력" } } : none(fill(TEXT.noInputs, combo));
|
||||
} catch (error) {
|
||||
return none(fill(TEXT.inputsFailed, why(error)));
|
||||
@@ -232,6 +237,8 @@ export interface StructurePanelOptions {
|
||||
onEdit: (column: string, label: string, kind: EditKind) => void;
|
||||
/** 집계표에 저장 안 한 고침이 있으면 버릴지 물음 — 취소면 false */
|
||||
confirmLeave: () => Promise<boolean>;
|
||||
/** 「선택 입력」 카드에서 자리를 골랐음 — 저장 안 한 고침 표시 */
|
||||
onDirty?: () => void;
|
||||
}
|
||||
|
||||
export interface StructurePanelHandle {
|
||||
@@ -240,6 +247,8 @@ export interface StructurePanelHandle {
|
||||
numbers: () => ColumnNumbers;
|
||||
/** 번호 목록 다시 받기 */
|
||||
reload: () => Promise<void>;
|
||||
/** 「선택 입력」 카드에서 고른 자리를 서버에 저장 — 집계표 [저장] 뒤에 부름(실패하면 던짐) */
|
||||
saveInputs: () => Promise<void>;
|
||||
/** 고른 열이 바뀜 — 같은 열이면 이름만 새로(CAD 를 다시 안 띄움) */
|
||||
show: (colId: string | null, columns: StructureColumn[]) => void;
|
||||
/** 보던 열을 다시 읽음 — 집계표 [저장] 뒤(서버가 새 열 파일 · 번호를 만듦) */
|
||||
@@ -311,11 +320,15 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
};
|
||||
};
|
||||
const sheets = [sheetCard("area"), sheetCard("material")];
|
||||
const inputs: InputsCardHandle = createInputsCard({
|
||||
isAdmin: opts.isAdmin,
|
||||
onDirty: () => opts.onDirty?.(),
|
||||
});
|
||||
|
||||
const root = el("div", {
|
||||
className: "m02-struct ui-sidebar-panel",
|
||||
attrs: { hidden: "" },
|
||||
children: [infoCard, ...sheets.map((c) => c.root)],
|
||||
children: [infoCard, ...sheets.map((c) => c.root), inputs.root],
|
||||
});
|
||||
attachCollapsible(root);
|
||||
|
||||
@@ -397,6 +410,7 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
root.hidden = true;
|
||||
column = null;
|
||||
doc = null;
|
||||
void inputs.show(null, null);
|
||||
return;
|
||||
}
|
||||
root.hidden = false;
|
||||
@@ -427,6 +441,8 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
c.number = String(book?.[PARTS[c.kind].field] ?? "");
|
||||
});
|
||||
paintBody(mine);
|
||||
// 집계표에 지금 고른 일위대가(저장 전일 수 있음) — 카드가 「먼저 저장」 안내를 고름
|
||||
void inputs.show(col.id, (col as { 일위대가?: string | null }).일위대가 ?? null);
|
||||
}
|
||||
|
||||
/** 글 열(NO · 측점 · 비고)은 구조물이 아니라 컨테이너를 닫음 */
|
||||
@@ -516,7 +532,9 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
numbers: () => numbers,
|
||||
reload: async () => {
|
||||
numbers = await fetchStructureNumbers().catch(() => ({}));
|
||||
inputs.invalidate(); // 새 열 · 바뀐 일위대가를 서버 항목 목록에서 다시 찾게
|
||||
},
|
||||
saveInputs: () => inputs.save(),
|
||||
show,
|
||||
refresh: (columns) => {
|
||||
const at = column;
|
||||
@@ -527,6 +545,7 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
destroy: () => {
|
||||
seq += 1;
|
||||
drop();
|
||||
inputs.destroy();
|
||||
root.remove();
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user