- 새 파일 = B08_Quantity_Summary_Table · Material_Tables · Earthwork_Tables · Hydro_Table · Milestone_Table - 화면 UI 파일 = 불러오기 · 그리기만 · 옛 B08 시험 = 옮긴 글 자리 따라 읽는 파일 더함 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Se7ytqbohmBQnfYpwYFnYf
113 lines
4.7 KiB
TypeScript
113 lines
4.7 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 { createButton, createCard } from "@ui/ui_template_elements";
|
|
import { createDataTable } from "@ui/ui_template_data_table";
|
|
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 {
|
|
const p = document.createElement("p");
|
|
p.className = "ui-general-block__empty";
|
|
p.textContent = text;
|
|
return p;
|
|
}
|
|
|
|
/** 표 한 장 — 공용 컨테이너(카드) 안에 공용 표 · 아래 줄 · 맨 아래 안내 · 경고 줄(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 ui-subtabs b08-earthwork__tabs";
|
|
tabs.setAttribute("role", "tablist");
|
|
const view = document.createElement("div");
|
|
let current: SheetId = "summary";
|
|
const select = (picked: SheetId): void => {
|
|
current = picked;
|
|
tabs.replaceChildren(
|
|
...SHEETS.map(({ id, label }) => {
|
|
const button = createButton({
|
|
label,
|
|
variant: id === picked ? "filled" : "ghost",
|
|
size: "sm",
|
|
onClick: () => id !== picked && select(id),
|
|
});
|
|
button.setAttribute("role", "tab");
|
|
button.setAttribute("aria-selected", String(id === picked));
|
|
button.dataset.b08EarthworkSheet = id;
|
|
return button;
|
|
}),
|
|
);
|
|
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);
|
|
});
|
|
}
|