feat(M02): 좌측 일위대가 하위 열 줄 — 「SU-… 이름」 · 누름 = onOpen({kind: "labor"})(39-2)
- 일위대가 하위 = 구조물 열마다 한 줄(번호 = /structures/numbers 일위대가번 · 없으면 「없음」) - Api_Fetch Kind 에 labor · StructureNumbers 에 일위대가번(39-1a 서버 칸) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BVPp2o6Mh2FZJr72yW3ofZ
This commit is contained in:
@@ -8,8 +8,9 @@ import { API_BASE_URL } from "@config/config_frontend";
|
||||
/** 층 이름 — 서버와 같은 글 */
|
||||
export type Layer = "system" | "company" | "personal" | "project";
|
||||
/** 서버 종류 — 화면의 「표 양식」 = table · 「도면 양식」 = drawing · 「구조물 도면」 = structure ·
|
||||
* 「면적산출」 = area · 「재료산출」 = material(둘 다 구조물집계표 열마다 한 통합문서) */
|
||||
export type Kind = "table" | "drawing" | "structure" | "area" | "material";
|
||||
* 「면적산출」 = area · 「재료산출」 = material(둘 다 구조물집계표 열마다 한 통합문서) ·
|
||||
* 「일위대가」 = labor(열마다 문서 · 39장) */
|
||||
export type Kind = "table" | "drawing" | "structure" | "area" | "material" | "labor";
|
||||
|
||||
export interface TemplateInfo {
|
||||
종류: Kind;
|
||||
@@ -153,6 +154,8 @@ export interface StructureNumbers {
|
||||
도번: string;
|
||||
면적번: string;
|
||||
재료번: string;
|
||||
/** 일위대가 `SU-######`(39장) */
|
||||
일위대가번: string;
|
||||
}
|
||||
|
||||
/** `{열 id: {도번, 면적번, 재료번}}` — 구조물 열만(글 열 · 없는 열은 키 없음 = 「없음」) */
|
||||
|
||||
@@ -48,17 +48,17 @@ const KINDS: { kind: Kind; label: () => string }[] = [
|
||||
{ kind: "table", label: () => L("M02_KindTable") },
|
||||
{ kind: "drawing", label: () => L("M02_KindDrawing") },
|
||||
];
|
||||
/** 구조물 열마다 한 줄씩인 하위 목록 — 종류 · 번호 칸(null = 열 줄 아직 없음) · 제목 ·
|
||||
* `all` = 맨 위 「전체 항목」 줄(PLAN 39-2) · 차례 = 구조물 도면 → 일위대가 → 면적산출 */
|
||||
/** 구조물 열마다 한 줄씩인 하위 목록 — 종류(편집 칸이 여는 `Kind`) · 번호 칸 · 제목 ·
|
||||
* `all` = 맨 위 「전체 항목」 줄(PLAN 39-2) · 차례 = 구조물 도면 → 일위대가(SU) → 면적산출 */
|
||||
type ColumnKind = "structure" | "labor" | "area" | "material";
|
||||
const COLUMN_KINDS: {
|
||||
kind: ColumnKind;
|
||||
key: keyof StructureNumbers | null;
|
||||
key: keyof StructureNumbers;
|
||||
label: () => string;
|
||||
all: boolean;
|
||||
}[] = [
|
||||
{ kind: "structure", key: "도번", label: () => L("M02_KindStructure"), all: true },
|
||||
{ kind: "labor", key: null, label: () => L("M02_KindLabor"), all: true },
|
||||
{ kind: "labor", key: "일위대가번", label: () => L("M02_KindLabor"), all: true },
|
||||
{ kind: "area", key: "면적번", label: () => L("M02_KindArea"), all: true },
|
||||
{ kind: "material", key: "재료번", label: () => L("M02_KindMaterial"), all: false },
|
||||
];
|
||||
@@ -262,10 +262,8 @@ export function buildSide(opt: SideOptions): SideHandle {
|
||||
|
||||
/** 하위 줄 — 「전체 항목」 + 구조물 열마다 하나 · 「번호 이름 변수값」(번호가 없으면 「없음」) */
|
||||
function paintRows(body: HTMLElement, k: (typeof COLUMN_KINDS)[number]): void {
|
||||
const { key } = k;
|
||||
const head = k.all ? [allRow(k.kind as AllKind)] : [];
|
||||
if (key === null) return body.replaceChildren(...head);
|
||||
const kind = k.kind as Kind; // 번호 칸이 있는 하위만 — 일위대가 열 줄은 번호(SU)가 선 뒤
|
||||
const { kind, key } = k;
|
||||
const head = k.all ? [allRow(kind as AllKind)] : [];
|
||||
body.replaceChildren(
|
||||
...head,
|
||||
...(columns.length
|
||||
@@ -318,7 +316,7 @@ export function buildSide(opt: SideOptions): SideHandle {
|
||||
opt.onOpen({ layer, projectId: null, kind: info.종류, name: info.이름 });
|
||||
}
|
||||
|
||||
async function selectColumn(col: StructureColumn, kind: Kind): Promise<void> {
|
||||
async function selectColumn(col: StructureColumn, kind: ColumnKind): Promise<void> {
|
||||
if (!isPicked(kind, col.id) && !(await opt.confirmLeave())) return;
|
||||
// 제목은 편집 화면이 문서 번호를 앞에 붙임(「SD010101 돌기슭막이 …」)
|
||||
opt.onOpen({ layer, projectId: null, kind, name: col.id, label: columnHead(col) });
|
||||
|
||||
@@ -34,7 +34,11 @@ def test_하위_차례_전체_항목_이름():
|
||||
kinds = side.split("const COLUMN_KINDS")[1].split("];")[0]
|
||||
order = [kinds.index(f'kind: "{k}"') for k in ("structure", "labor", "area")]
|
||||
assert order == sorted(order) # 구조물 도면 → 일위대가 → 면적산출
|
||||
assert 'label: () => L("M02_KindLabor"), all: true' in kinds
|
||||
assert 'kind: "labor", key: "일위대가번", label: () => L("M02_KindLabor"), all: true' in kinds
|
||||
# 일위대가 줄 = 열마다 「SU-… 이름」 · 누름 = onOpen({kind: "labor", name: 열}) — 같은 selectColumn 길
|
||||
assert "opt.onOpen({ layer, projectId: null, kind, name: col.id" in side
|
||||
api = _text("M02_MasterTemplete_Api_Fetch.ts")
|
||||
assert '| "labor";' in api and "일위대가번: string;" in api
|
||||
assert "onAll?: (kind: AllKind) => void;" in side # 화면은 ItemList(39-5) · 페이지가 이음
|
||||
assert "if (!opt.onAll || allPicked === kind || !(await opt.confirmLeave())) return;" in side
|
||||
assert 'return void selectAll("labor");' in side # 해시 open=일위대가
|
||||
|
||||
Reference in New Issue
Block a user