Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ACSGaHdLgnkEkoA4LDtMU
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
/* =============================================================================
|
|
* M01_LB_Wizard_Parts.ts
|
|
* 단계 안내 곁부품 — 서버 읽기(절 · 표) · 표 → WTable · 원문 표 미리 보기 · `M01_LB_Wizard.ts` 가 부름
|
|
* ========================================================================== */
|
|
|
|
import { API_BASE_URL } from "@config/config_frontend";
|
|
import { el } from "@ui/ui_template_elements";
|
|
import { ApiError } from "../M01_MasterData_UI_Logic_Api";
|
|
import type { Role, WTable } from "./M01_LB_Wizard_Build";
|
|
|
|
export async function get<T>(path: string, params: Record<string, string>): Promise<T> {
|
|
const res = await fetch(`${API_BASE_URL}/m01${path}?${new URLSearchParams(params)}`, {
|
|
credentials: "include",
|
|
});
|
|
const data = (await res.json().catch(() => ({}))) as { detail?: unknown } & T;
|
|
if (!res.ok) throw new ApiError(res.status, data.detail ?? res.statusText);
|
|
return data;
|
|
}
|
|
|
|
export interface SectionItem {
|
|
section: string;
|
|
title: string;
|
|
chapter: string;
|
|
tables: number;
|
|
logics: number;
|
|
}
|
|
export interface TableHead {
|
|
file: string;
|
|
키: string;
|
|
이름: string;
|
|
기준: string;
|
|
조건: Record<string, string>;
|
|
값칸: Record<string, string>;
|
|
count: number;
|
|
}
|
|
|
|
/** 서버 표 답 → WTable */
|
|
export function toTable(raw: WTable & { 키: string }, file: string): WTable {
|
|
return {
|
|
key: raw.키,
|
|
file,
|
|
이름: raw.이름,
|
|
기준: raw.기준 ?? "",
|
|
출처: raw.출처 ?? "",
|
|
조건: raw.조건,
|
|
값칸: raw.값칸,
|
|
범위규칙: raw.범위규칙 ?? null,
|
|
줄: raw.줄,
|
|
주: raw.주 ?? [],
|
|
};
|
|
}
|
|
|
|
const cellText = (v: unknown): string =>
|
|
Array.isArray(v)
|
|
? v.map((x) => x ?? "").join("~")
|
|
: v === null || v === undefined
|
|
? ""
|
|
: String(v);
|
|
|
|
/** 원문 표 앞 몇 줄 + 주 — 칸 머리 색 = 역할 */
|
|
export function tablePreview(
|
|
tb: WTable,
|
|
labels: { preview: string; notes: string },
|
|
roles?: Record<string, Role>,
|
|
): HTMLElement {
|
|
const cols = [...Object.keys(tb.조건), ...Object.keys(tb.값칸)];
|
|
const head = el("tr", {
|
|
children: cols.map((c) =>
|
|
el("th", { className: `is-${roles?.[c] ?? (c in tb.조건 ? "조건" : "결과")}`, text: c }),
|
|
),
|
|
});
|
|
const rows = tb.줄
|
|
.slice(0, 6)
|
|
.map((r) => el("tr", { children: cols.map((c) => el("td", { text: cellText(r[c]) })) }));
|
|
return el("div", {
|
|
className: "m01-lbw__table",
|
|
children: [
|
|
el("h5", { text: `${labels.preview} — ${tb.이름} (${tb.기준 || "—"})` }),
|
|
el("div", {
|
|
className: "m01-lbw__scroll",
|
|
children: [el("table", { children: [head, ...rows] })],
|
|
}),
|
|
...(tb.줄.length > 6
|
|
? [el("p", { className: "m01-lbw__muted", text: `… ${tb.줄.length} 줄` })]
|
|
: []),
|
|
...(tb.주.length
|
|
? [
|
|
el("h5", { text: labels.notes }),
|
|
...tb.주.map((n) => el("p", { className: "m01-lbw__note-line", text: n })),
|
|
]
|
|
: []),
|
|
],
|
|
});
|
|
}
|