feat(b09): 좌측 하단 고정 줄 — [박스보기|호표보기] 한 설정(묶음 탭 셋 · 옛 탭별 값 하나로 · 탭 줄 토글 걷음) · [하이퍼링크|팝업] 스위치(pref global · 기본 팝업) · DRAFT.actions 자리 · [?][저장][내역 초기화] 그대로 (303-1 · 304-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
/* =============================================================================
|
||||
* B09_Estimation_UI_Tabs_Groups.ts
|
||||
* B09 묶음 탭 셋(PLAN 171-3) — 일위대가표 · 중기사용료 · 단가산출근거 = 공용 묶음 카드(171-2) 기본 ·
|
||||
* [표로 보기] = 공용 표 그대로(맞은편 단추 = [박스보기]).
|
||||
* 호표보기 = 공용 표 그대로 · 고름 = 좌측 하단 [박스보기|호표보기] 한 벌(304-1 · 셋 탭 함께).
|
||||
*
|
||||
* 카드 = 탭 표 줄(`TabTable.rows`)을 호표(줄 키 앞머리)마다 묶음 — 값 · 풍선 · 누름 이동은 표와 같음
|
||||
* 머리 줄 = 묶음 첫 줄 · 합계 줄 = 키 끝 `|합계` · `|총계` · 그 밖 = 몸 줄(표 줄 번호 그대로)
|
||||
* 목록표에서 온 호표(181-2) = 박스 붉은 외곽선 · 표 보기 = 그 호표 줄 구간 전체 붉은 외곽선
|
||||
* 248-1 빨강 하나(공용 고름 강조 안 붙임 · 스크롤만) · 줄 · 카드 누름 · 방향키 · Esc = 빨강 풂 ·
|
||||
* 누른 줄만 고름(is-focus) · Esc = 고름도 풂
|
||||
* 보기 · 가로 열 수 기억 = `b_page_state`(`b09-group-view` · `b09-group-cols` · 탭마다) · 못 읽으면 카드 · 2
|
||||
* 보기 단추 · 가로 열 수(202-1) = 페이지 보조 탭 줄 오른쪽(`setTools`) · 안내 글 = 표 · 카드 판 맨 아래
|
||||
* 보기 기억 = `b_page_state`(`b09-group-view` · 한 값 · 옛 탭별 값은 첫 읽기에 하나로) · 가로 열 수 =
|
||||
* `b09-group-cols`(탭마다) · 못 읽으면 카드 · 2
|
||||
* 가로 열 수(202-1) = 페이지 보조 탭 줄 오른쪽(`setTools`) · 안내 글 = 표 · 카드 판 맨 아래
|
||||
* 안내 글 길면 한 줄 줄임표 + 공용 호버로 전문(200-1)
|
||||
* 278-2 단가산출근거 박스 = 머리 줄(`|머리n`)을 운반 단가 창 ③ 칸 꼴로(`headSteps` 한 벌 · 몸 위 칸) ·
|
||||
* 출처 = 그 칸 맨 위 · 호표 줄 · 총계 = 그대로 · 묶음 자료(`tabGroups`) · 표는 안 바뀜
|
||||
* ========================================================================== */
|
||||
|
||||
import type { DataRow, DataTable } from "@ui/ui_template_data_table";
|
||||
import { createButton } from "@ui/ui_template_elements";
|
||||
import { attachHoverInfo } from "@ui/ui_template_hover_info";
|
||||
import {
|
||||
clampColumns,
|
||||
@@ -38,10 +38,8 @@ export const GROUP_TABS: TabId[] = ["dg", "machine_blocks", "sg"];
|
||||
|
||||
export const isGroupTab = (tab: TabId): boolean => GROUP_TABS.includes(tab);
|
||||
|
||||
/** 단추 글 = 바꿀 보기 이름 */
|
||||
export const viewLabel = (view: GroupView): string => (view === "cards" ? "표로 보기" : "박스보기");
|
||||
|
||||
export const flipView = (view: GroupView): GroupView => (view === "cards" ? "table" : "cards");
|
||||
/** 단추 글 = 그 보기 이름(304-1 좌측 스위치) */
|
||||
export const viewLabel = (view: GroupView): string => (view === "cards" ? "박스보기" : "호표보기");
|
||||
|
||||
type Saved = Record<string, unknown> | null;
|
||||
|
||||
@@ -53,19 +51,39 @@ const saved = (name: "b09-group-view" | "b09-group-cols"): Saved => {
|
||||
}
|
||||
};
|
||||
|
||||
/** 고른 보기 — 모르는 값 · 못 읽음 = 카드 */
|
||||
export const readGroupView = (tab: TabId, kept: Saved = saved("b09-group-view")): GroupView =>
|
||||
kept?.[tab] === "table" ? "table" : "cards";
|
||||
/** 고른 보기(셋 탭 한 값) — 옛 탭별 값 = dg · 다른 탭 차례 · 모르는 값 · 못 읽음 = 카드 */
|
||||
export function readGroupView(kept: unknown = saved("b09-group-view")): GroupView {
|
||||
const old = kept && typeof kept === "object" ? (kept as Record<string, unknown>) : null;
|
||||
const value = old ? (old.dg ?? old.machine_blocks ?? old.sg) : kept;
|
||||
return value === "table" ? "table" : "cards";
|
||||
}
|
||||
|
||||
/** 이 화면 안 보기(기억이 안 돼도 고른 보기 유지) */
|
||||
let chosen: GroupView | null = null;
|
||||
|
||||
/** 지금 보기 — 첫 읽기에 옛 탭별 값을 한 값으로 옮겨 적음 */
|
||||
export function groupView(): GroupView {
|
||||
if (chosen) return chosen;
|
||||
const kept = saved("b09-group-view");
|
||||
chosen = readGroupView(kept);
|
||||
if (kept && typeof kept === "object") chooseGroupView(chosen);
|
||||
return chosen;
|
||||
}
|
||||
|
||||
export function chooseGroupView(view: GroupView): void {
|
||||
chosen = view;
|
||||
try {
|
||||
writeState("b09-group-view", view);
|
||||
} catch {
|
||||
// 기억 못 해도 이 화면 안에서는 고른 값 그대로
|
||||
}
|
||||
}
|
||||
|
||||
/** 고른 가로 열 수 — 1~4 · 모르는 값 = 2 */
|
||||
export const readGroupCols = (tab: TabId, kept: Saved = saved("b09-group-cols")): number =>
|
||||
clampColumns(kept?.[tab]);
|
||||
|
||||
export function rememberGroup(
|
||||
name: "b09-group-view" | "b09-group-cols",
|
||||
tab: TabId,
|
||||
value: unknown,
|
||||
): void {
|
||||
export function rememberGroup(name: "b09-group-cols", tab: TabId, value: unknown): void {
|
||||
try {
|
||||
writeState(name, { ...(saved(name) ?? {}), [tab]: value });
|
||||
} catch {
|
||||
@@ -244,33 +262,18 @@ export function unpickOnRelease(root: HTMLElement): void {
|
||||
listenKeys();
|
||||
}
|
||||
|
||||
/** 이 화면 안 보기(기억이 안 돼도 바꾼 보기 유지) */
|
||||
const chosen = new Map<TabId, GroupView>();
|
||||
|
||||
/** 묶음 탭 — 카드 = 카드 판 + 안내 글 · 표 = 표 + 안내 글 · 보기 단추 · 열 수 = `setTools`(보조 탭 줄 오른쪽) */
|
||||
/** 묶음 탭 — 카드 = 카드 판 + 안내 글 · 표 = 표 + 안내 글 · 열 수 = `setTools`(보조 탭 줄 오른쪽) */
|
||||
export function renderGroupPanel(o: {
|
||||
tab: TabId;
|
||||
spec: TabTable;
|
||||
hint: HTMLElement | null;
|
||||
focus?: string;
|
||||
goto: (link: Link | null) => void;
|
||||
goto: (link: Link | null, anchor?: Element | null) => void;
|
||||
makeTable: (rowClass?: (index: number) => string | null) => DataTable;
|
||||
redraw: () => void;
|
||||
setTools: (tools: HTMLElement[]) => void;
|
||||
}): HTMLElement[] {
|
||||
const view = chosen.get(o.tab) ?? readGroupView(o.tab);
|
||||
const view = groupView();
|
||||
const lead = lineHint(o.hint);
|
||||
const toggle = createButton({
|
||||
label: viewLabel(view),
|
||||
variant: "ghost",
|
||||
size: "sm",
|
||||
onClick: () => {
|
||||
chosen.set(o.tab, flipView(view));
|
||||
rememberGroup("b09-group-view", o.tab, flipView(view));
|
||||
o.redraw();
|
||||
},
|
||||
});
|
||||
toggle.dataset.b09GroupView = view;
|
||||
const at = o.focus === undefined ? -1 : rowIndex(o.spec.rows, o.focus);
|
||||
if (view === "cards") {
|
||||
const first = o.spec.columns[0]?.key ?? "";
|
||||
@@ -281,19 +284,18 @@ export function renderGroupPanel(o: {
|
||||
: tabGroups(o.tab, o.spec),
|
||||
columns: readGroupCols(o.tab),
|
||||
onColumns: (n) => rememberGroup("b09-group-cols", o.tab, n),
|
||||
onPick: (i) => o.goto(o.spec.link?.(i, first) ?? null),
|
||||
onPick: (i) =>
|
||||
o.goto(o.spec.link?.(i, first) ?? null, cards.querySelector(`[data-at="${i}"]`)),
|
||||
focus: at,
|
||||
money: numberFormat(o.spec, "sum"),
|
||||
qty: numberFormat(o.spec, "qty"),
|
||||
actions: [toggle],
|
||||
placeTools: o.setTools, // 202-1 가로 열 수 · 보기 단추 = 보조 탭 줄 오른쪽
|
||||
placeTools: o.setTools, // 202-1 가로 열 수 = 보조 탭 줄 오른쪽
|
||||
});
|
||||
cards.dataset.b09Table = o.tab;
|
||||
live = { root: cards, unpick: (esc) => unpickCards(cards, esc) };
|
||||
listenKeys();
|
||||
return [cards, ...(lead ? [lead] : [])];
|
||||
}
|
||||
o.setTools([toggle]);
|
||||
let range = pickRange(o.spec.rows, o.focus);
|
||||
let chose = -1; // 누른 줄(다시 그려도 유지)
|
||||
const table = o.makeTable((i) => (i === chose ? "is-focus" : pickClass(range, i)));
|
||||
|
||||
Reference in New Issue
Block a user