- 위 · 보조 탭 줄 = 부품 탭(fillTabs · 밑줄 · 알약) · B09 좌측 스위치 = 분할 고르기 - 연결 칩 · 검사 탭 이름 · 끌기 태그 = 배지 · 이정표 도구 · 머리 줄 · 저장 줄 = 도구줄 · 구간 고침 · 행 고름 창 = 떠 있는 판 - 안내 · 빈 줄 · 상태 글 = 보조 글 · 운반 칸 = 카드 · 인쇄 미리보기 좌측 줄 = B09 dock 한 벌 · 쪽 체크 = 라디오 · 체크 부품 - 시험 흉내 틀 · 문구 맞춤 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
104 lines
4.4 KiB
TypeScript
104 lines
4.4 KiB
TypeScript
/* =============================================================================
|
|
* B08_Quantity_UI_Earthwork.ts
|
|
* 토공 탭(PLAN 61-3 · 69-2 · 69-3) — 보조 탭 넷 = 토공집계표 · 토적표 · 평균운반거리 · 종방향 무대운반거리.
|
|
*
|
|
* GET …/quantity/earthwork 한 번(서버 단독 · 읽기만) — 네 장이 같은 응답을 나눠 그림.
|
|
* 토적표 = 줄 측점 · 칸 = 사용자 견본(절토 토사 · 연암 · 측구파기 토사 · 암 각 단면적 · 입적 ·
|
|
* 보정량 · 보정량계 · 성토 · 유용토 · 차인토량 · 누가토량 · 면고르기 · 지장목제거 · 제근 · 노면정리 각
|
|
* 거리 · 면적) · 맨 아래 합계 줄. 첫 측점은 앞이 없어 입적 · 면적이 빈 값(—).
|
|
* 표 = 공용 많은 자료 표(`ui_template_data_table` · PLAN 70) · 카드 안 · 나머지 셋은 `…_Earthwork_Sheets`.
|
|
* 절토 연암 · 경암 = 암 × 좌측 패널 비율 · 암 C = 비율 가중 — 조작 중 같은 식으로 바로 다시 셈
|
|
* (`…_Options_Calc` · PLAN 122 · 125-1).
|
|
* 자료 읽기 · 표 짜기 = `B08_Quantity_Earthwork_Tables`(화면 없음 · 인쇄 미리보기도 씀 · 302-3)
|
|
* ========================================================================== */
|
|
|
|
import { createCard } from "@ui/ui_template_elements";
|
|
import { createText } from "@ui/ui_template_text";
|
|
import { createDataTable } from "@ui/ui_template_data_table";
|
|
import { fillTabs } from "../A00_Common/b_page_tabs";
|
|
import { footNote } from "./B08_Quantity_UI_Foot";
|
|
import {
|
|
EARTHWORK_SHEETS,
|
|
earthworkSheetOptions,
|
|
loadEarthwork,
|
|
type EarthworkTable,
|
|
} from "./B08_Quantity_Earthwork_Tables";
|
|
import {
|
|
renderEarthworkSummary,
|
|
renderFreeHaul,
|
|
renderHaulDistance,
|
|
} from "./B08_Quantity_UI_Earthwork_Sheets";
|
|
import { onOptionsChange } from "./B08_Quantity_UI_Options";
|
|
|
|
export function note(text: string): HTMLElement {
|
|
return createText(text, "muted", 14);
|
|
}
|
|
|
|
/** 표 한 장 — 공용 컨테이너(카드) 안에 공용 표 · 아래 줄 · 맨 아래 안내 · 경고 줄(202-1) */
|
|
export function tableCard(
|
|
info: HTMLElement[],
|
|
table: HTMLElement,
|
|
after: HTMLElement[] = [],
|
|
): HTMLElement {
|
|
return createCard({ body: [table, ...after, ...info] });
|
|
}
|
|
|
|
function renderSheet(host: HTMLElement, table: EarthworkTable, interval: number): void {
|
|
if (!table.rows.length) {
|
|
host.replaceChildren(note("측점 단면적이 아직 없습니다 — 횡단 설계를 먼저 마치세요."));
|
|
return;
|
|
}
|
|
const flagged = table.rows.filter((row) => row.notes.length);
|
|
const info = [
|
|
footNote(
|
|
`노선 ${table.route_id}${table.confirmed ? "(확정)" : "(확정 전 최신 노선)"} · ` +
|
|
`측점 ${table.station_count} · 단위 m · ㎡ · ㎥`,
|
|
),
|
|
...(flagged.length ? [footNote(`* ${flagged[0].notes[0]} — ${flagged.length}곳`)] : []),
|
|
];
|
|
const grid = createDataTable({ ...earthworkSheetOptions(table, interval), fillViewport: true });
|
|
grid.root.dataset.b08Earthwork = "table";
|
|
host.replaceChildren(tableCard(info, grid.root));
|
|
}
|
|
|
|
const SHEETS = EARTHWORK_SHEETS;
|
|
|
|
type SheetId = (typeof SHEETS)[number]["id"];
|
|
|
|
export async function renderEarthwork(host: HTMLElement, projectId: string): Promise<void> {
|
|
host.replaceChildren(note("토공 수량을 만드는 중…"));
|
|
let loaded: Awaited<ReturnType<typeof loadEarthwork>>;
|
|
try {
|
|
loaded = await loadEarthwork(projectId);
|
|
} catch (error) {
|
|
host.replaceChildren(note(`토공 수량을 불러오지 못했습니다 — ${String(error)}`));
|
|
return;
|
|
}
|
|
const { table, interval, applyRock } = loaded;
|
|
|
|
const tabs = document.createElement("div");
|
|
tabs.className = "b08-quantity__tabs b08-earthwork__tabs";
|
|
const view = document.createElement("div");
|
|
let current: SheetId = "summary";
|
|
const select = (picked: SheetId): void => {
|
|
current = picked;
|
|
fillTabs(tabs, {
|
|
tabs: SHEETS.map(({ id, label }) => ({ key: id, label })),
|
|
value: picked,
|
|
kind: "pill",
|
|
data: "b08EarthworkSheet",
|
|
onChange: (id) => select(id as SheetId),
|
|
});
|
|
if (picked === "sheet") renderSheet(view, table, interval);
|
|
else if (picked === "summary") renderEarthworkSummary(view, table);
|
|
else if (picked === "haul") renderHaulDistance(view, table);
|
|
else renderFreeHaul(view, table);
|
|
};
|
|
host.replaceChildren(tabs, view);
|
|
select("summary");
|
|
onOptionsChange(host, () => {
|
|
applyRock();
|
|
select(current);
|
|
});
|
|
}
|