merge(M02): origin/sub_laptop_1 받음 — ItemCards · Structure 충돌 풂(카드 labor · copyPartFrom 살림 · 재료산출 지움 반영)
- ItemCards 카드 글 = 도면 · 면적산출 · 일위대가(material 빠짐) - Structure.ts = copyPartFrom 하나(옛 COPY 표 · copyArea · copyStructure 지움) · 일위대가 카드 열기 살림 - Api_Fetch copyPartFrom 종류에서 material 뺌(재료산출 지움 39-7a) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BVPp2o6Mh2FZJr72yW3ofZ
This commit is contained in:
@@ -25,8 +25,7 @@ import { openModal } from "@ui/ui_template_modal";
|
||||
import type { LinkOptions } from "../A00_Common/spreadsheet/spreadsheet_links";
|
||||
import { fetchUsableCombos } from "./M02_MasterTemplete_Labor_Api";
|
||||
import {
|
||||
copyArea,
|
||||
copyStructure,
|
||||
copyPartFrom,
|
||||
fetchLaborPills,
|
||||
fetchStructureNumbers,
|
||||
getActiveLayer,
|
||||
@@ -39,7 +38,7 @@ import {
|
||||
createItemCards,
|
||||
PART_FIELD,
|
||||
PART_WORD,
|
||||
type EditKind,
|
||||
type CardKind,
|
||||
type SheetCardControl,
|
||||
type SheetEditOptions,
|
||||
type SheetKind,
|
||||
@@ -48,7 +47,7 @@ import { layerSource } from "./M02_MasterTemplete_ItemSource";
|
||||
import { pickHere, pickedName, type From } from "./M02_MasterTemplete_ItemPick";
|
||||
import "./M02_MasterTemplete_Structure.css";
|
||||
|
||||
export type { EditKind, SheetKind } from "./M02_MasterTemplete_ItemCards";
|
||||
export type { CardKind, EditKind, SheetKind } from "./M02_MasterTemplete_ItemCards";
|
||||
|
||||
/** 구조물 도면이 걸리는 집계표 이름 — 서버 `M02_MasterTemplete_Store.STRUCTURE_TABLE` 과 같은 글 */
|
||||
export const STRUCTURE_TABLE = "구조물집계표";
|
||||
@@ -58,26 +57,20 @@ const TEXT = {
|
||||
find: "찾기",
|
||||
clear: "비움",
|
||||
none: "고를 것이 없음",
|
||||
pickPrice: "일위대가 고르기",
|
||||
combosFailed: "일위대가 목록을 못 받음 — {value}",
|
||||
saveFirst: "새 열은 구조물 조합을 먼저 저장해야 번호가 생김",
|
||||
overwrite: "{from} 의 {what} 내용을 {to} 에 덮어씀 — 번호 · 열은 그대로",
|
||||
pickCopy: "{value} 복사해 가져오기",
|
||||
copied: "복사해 가져옴",
|
||||
acrossLater: "다른 곳(층 · 사람)에서 가져오기는 서버 길이 선 뒤 — 지금은 같은 곳만",
|
||||
copyFailed: "복사 실패 — {value}",
|
||||
noPills: "이 열 일위대가에 담은 로직 · 자재가 없어 알약 없음 — 일위대가 상세에서 담음",
|
||||
pillsFailed: "일위대가 알약을 못 받음 — {value}",
|
||||
discardCards: "카드(도면 · 면적산출)에 저장 안 한 고침이 있음 — 버리고 넘어갈까?",
|
||||
};
|
||||
|
||||
/** 집계표 열 하나에 딸린 문서 셋 — 번호 칸 · 이름 · 복사 */
|
||||
const COPY: Record<EditKind, (to: string, from: string) => Promise<void>> = {
|
||||
structure: copyStructure,
|
||||
area: copyArea,
|
||||
};
|
||||
/** 집계표 줄 열쇠 → 문서 */
|
||||
const ROW_KIND: Record<string, EditKind> = {
|
||||
const ROW_KIND: Record<string, CardKind> = {
|
||||
"s:price": "labor", // 일위대가 = 열마다 문서(39장) — 다른 항목 것을 복사해 옴
|
||||
"s:drawing": "structure",
|
||||
"s:area": "area",
|
||||
};
|
||||
@@ -307,7 +300,7 @@ export interface StructurePanelOptions {
|
||||
isAdmin: boolean;
|
||||
/** [도면 수정] · [면적산출 수정] — 그 열을 CAD · 스프레드시트 전체 편집으로 엶
|
||||
* (페이지의 `open`) · label 은 화면 제목에 씀 */
|
||||
onEdit: (column: string, label: string, kind: EditKind) => void;
|
||||
onEdit: (column: string, label: string, kind: CardKind) => void;
|
||||
/** 집계표에 저장 안 한 고침이 있으면 버릴지 물음 — 취소면 false */
|
||||
confirmLeave: () => Promise<boolean>;
|
||||
/** 카드 고침을 버리지 않고 머묾 — 표의 고른 열을 되돌림(31-3) */
|
||||
@@ -350,6 +343,7 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
warnOnFail: (id) => !!numbers[id],
|
||||
// 「복사해 가져오기」 · 빈 카드 [복사 생성](39-5) — 집계표 줄 「조회 후 선택」 과 같은 길
|
||||
onImport: (kind) => void pickCopy(kind, shown ?? undefined),
|
||||
labor: () => void openEdit("labor"), // 일위대가 카드(보기 갈래 · 39-3) — 도면 다음
|
||||
// 면적산출 카드 미리보기 수정(31-3) — 전체 편집기와 같은 알약 · 저장 길
|
||||
sheetEdit: {
|
||||
can: () => opts.isAdmin,
|
||||
@@ -384,18 +378,14 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
if (col) cards.setLabel((columnLabel = columnHead(col))); // 머리를 고쳤을 수 있음
|
||||
};
|
||||
|
||||
const pickPrice = async (colId: string, columns: StructureColumn[]): Promise<string | null> => {
|
||||
const col = columns.find((c) => c.id === colId);
|
||||
const got = await pickCombo(col ? `${TEXT.pickPrice} — ${columnHead(col)}` : TEXT.pickPrice);
|
||||
return got ? got.key : null;
|
||||
};
|
||||
|
||||
/** 다른 항목의 도면 · 면적산출(…)을 골라 내용만 복사(39-5) — 탭 = 읽을 수 있는 곳 · 덮어쓰기 확인 ·
|
||||
* 번호 · 열은 그대로 · 보고 있던 열이면 다시 읽음 · 집계표 줄 「조회 후 선택」 · 카드 「복사해 가져오기」가 씀 */
|
||||
const pickCopy = async (kind: EditKind, to: StructureColumn | undefined): Promise<void> => {
|
||||
const pickCopy = async (kind: CardKind, to: StructureColumn | undefined): Promise<void> => {
|
||||
const word = PART_WORD[kind];
|
||||
const toNo = to && numbers[to.id]?.[PART_FIELD[kind]];
|
||||
if (!to || !toNo) return void showToast(TEXT.saveFirst, "error");
|
||||
// 카드에 저장 안 한 고침 — 가져온 뒤 카드를 다시 읽어 버려지니 먼저 물음
|
||||
if (cards.dirty() && !(await showConfirmDialog(TEXT.discardCards))) return;
|
||||
const target = `${toNo} ${columnHead(to)}`;
|
||||
const here = { layer: getActiveLayer(), owner: getActiveOwner() };
|
||||
const same = (from: From): boolean => from.layer === here.layer && from.owner === here.owner;
|
||||
@@ -409,10 +399,18 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
.replace("{what}", word)
|
||||
.replace("{to}", target),
|
||||
});
|
||||
if (!picked || !("row" in picked)) return;
|
||||
if (!picked) return;
|
||||
try {
|
||||
if (!same(picked.from)) throw new Error(TEXT.acrossLater); // 층 넘는 복사 길(39-1b) 뒤에 이음
|
||||
await COPY[kind](to.id, picked.row.열);
|
||||
// 같은 곳 = 다른 열 · 다른 층 · 사람 = 원본 층 · 실무문서 = 조합 키 → 일위대가(39-1b)
|
||||
if ("combo" in picked)
|
||||
await copyPartFrom(kind, to.id, picked.combo.키, { layer: "practice", owner: null });
|
||||
else
|
||||
await copyPartFrom(
|
||||
kind,
|
||||
to.id,
|
||||
picked.row.열,
|
||||
same(picked.from) ? null : { layer: picked.from.layer, owner: picked.from.owner },
|
||||
);
|
||||
showToast(TEXT.copied, "success");
|
||||
if (column === to.id) void load(shown);
|
||||
} catch (error) {
|
||||
@@ -426,7 +424,6 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
columns: StructureColumn[],
|
||||
): Promise<string | null> => {
|
||||
if (!opts.isAdmin || !colId) return null;
|
||||
if (row === "s:price") return pickPrice(colId, columns);
|
||||
if (ROW_KIND[row])
|
||||
await pickCopy(
|
||||
ROW_KIND[row],
|
||||
@@ -435,7 +432,7 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane
|
||||
return null;
|
||||
};
|
||||
|
||||
async function openEdit(kind: EditKind): Promise<void> {
|
||||
async function openEdit(kind: CardKind): Promise<void> {
|
||||
const at = column;
|
||||
if (!at) return;
|
||||
// 저장 전 새 열(분류 더하기) — 문서 · 번호가 아직 없음 · 떠나면 집계표 고침까지 버리게 됨
|
||||
|
||||
Reference in New Issue
Block a user