Merge remote-tracking branch 'origin/sub_laptop_1' into sub_laptop_6
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
* · 같은 로직 두 번 · 같은 자재 두 번 막음 · 빈 일위대가도 저장 됨
|
||||
* · 오른쪽 「원문」 접는 패널(47-4 · 상세만 · 공용 `ui_template_side_panels`) = 고른 줄 로직의 출처 원문
|
||||
* · 서고 모드(50-3 · `mode`) = 단가승격 · 사전조합 — 이름 칸 · 단가산출 로직 표 · 원문만(자재 · 면적 · 다이어그램 없음) ·
|
||||
* 승격은 로직 한 줄(입력값 고정 · 더하기 · 순서 · 수량 없음) · 사전조합 = [추가] · 수량 손 입력(기본 1) · 순서 · 삭제
|
||||
* 승격은 로직 한 줄(입력값 고정 · 더하기 · 순서 · 수량 없음) · 사전조합 = [로직 추가](같은 고르기 창 · 서고 줄만) · 수량 손 입력(기본 1) · 순서 · 삭제
|
||||
* ========================================================================== */
|
||||
|
||||
import { createButton, createInputField, el, showToast } from "@ui/ui_template_elements";
|
||||
@@ -378,22 +378,20 @@ export function mountLaborDetail(
|
||||
changed();
|
||||
},
|
||||
};
|
||||
/** 사전조합 [추가] — 서고 줄만 고르기(위 층만 · 자기 자신 · 순환은 [저장] 때 서버 422) */
|
||||
const addRef = createButton({
|
||||
label: tc("Lib_AddRow"),
|
||||
variant: "filled",
|
||||
onClick: () => openLogicPicker(() => undefined, { ...library, only: true }),
|
||||
});
|
||||
const addLogic = createButton({
|
||||
label: tc("AddLogic"),
|
||||
variant: "filled",
|
||||
onClick: () =>
|
||||
openLogicPicker((x) => {
|
||||
if (cur.담은로직.some((r) => r.로직 === x.키))
|
||||
return showToast(tc("Labor_Already").replace("{value}", `${x.키} ${x.이름}`), "error");
|
||||
cur.담은로직.push({ 로직: x.키, 별칭: null, 메모: null, 입력값: {}, 수량: null });
|
||||
void loadLogics().then(() => changed());
|
||||
}, library),
|
||||
openLogicPicker(
|
||||
(x) => {
|
||||
if (cur.담은로직.some((r) => r.로직 === x.키))
|
||||
return showToast(tc("Labor_Already").replace("{value}", `${x.키} ${x.이름}`), "error");
|
||||
cur.담은로직.push({ 로직: x.키, 별칭: null, 메모: null, 입력값: {}, 수량: null });
|
||||
void loadLogics().then(() => changed());
|
||||
// 사전조합 = 같은 창 · 서고 줄만(위 층만 · 자기 자신 · 순환은 [저장] 때 서버 422)
|
||||
},
|
||||
lib ? { ...library, only: true } : library,
|
||||
),
|
||||
});
|
||||
const addMat = createButton({
|
||||
label: tc("Labor_AddMat"),
|
||||
@@ -478,12 +476,8 @@ export function mountLaborDetail(
|
||||
],
|
||||
}),
|
||||
]),
|
||||
// 승격 = 로직 한 줄(새로 만들 때 고름) · 사전조합 = [추가] 서고 줄만 고르기(51-6)
|
||||
section(
|
||||
tc("Logics_Title"),
|
||||
opt.card || promote ? null : lib ? addRef : addLogic,
|
||||
logicHost,
|
||||
),
|
||||
// 승격 = 로직 한 줄(새로 만들 때 고름) · 사전조합 = 같은 [로직 추가] · 서고 줄만(51-10)
|
||||
section(tc("Logics_Title"), opt.card || promote ? null : addLogic, logicHost),
|
||||
...(lib ? [] : [section(tc("Labor_Mats"), opt.card ? null : addMat, matHost)]),
|
||||
...(opt.card || lib ? [] : [dgBox]),
|
||||
],
|
||||
|
||||
@@ -124,7 +124,6 @@ const TEXT = {
|
||||
Lib_Unit: ["단위", "Unit"],
|
||||
Lib_Base: ["기준 금액", "Base amount"],
|
||||
Lib_Date: ["고친 날", "Modified"],
|
||||
Lib_AddRow: ["추가", "Add"],
|
||||
} as const satisfies Record<string, readonly [string, string]>;
|
||||
|
||||
export type ComboTextKey = keyof typeof TEXT;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* 일위대가 조합 서고 목록표(51-4) — 좌측 항목(단가산출 승격 · 일위대가 사전조합)을 누르면 상세 칸에 뜸.
|
||||
* 표 = 고름 · 키 · 이름 · 단위 · 기준 금액(서버 1 단위 계) · 고친 날 · 줄 누름 = 그 문서 상세.
|
||||
* 머리 [생성] · [복사](고른 줄) · [삭제](고른 줄 · 쓰는 곳 있으면 서버 409 까닭 그대로).
|
||||
* 꼴 = M01 단가산출 로직 목록 — 찾기 줄(`buildHeadFilters`) · 쪽(`buildPager`) · 표(`m01-master__grid`) 를 M01 에서 import.
|
||||
* ========================================================================== */
|
||||
|
||||
import {
|
||||
@@ -14,6 +15,9 @@ import {
|
||||
} from "@ui/ui_template_elements";
|
||||
import { t as L } from "@ui/ui_template_locale";
|
||||
import { openModal } from "@ui/ui_template_modal";
|
||||
import { buildPager } from "../M01_MasterData/M01_MasterData_UI_Cells";
|
||||
import { buildHeadFilters } from "../M01_MasterData/M01_MasterData_UI_Head";
|
||||
import "../M01_MasterData/M01_MasterData_UI_Style.css";
|
||||
import {
|
||||
deleteLayerTemplate,
|
||||
deleteTemplate,
|
||||
@@ -41,6 +45,7 @@ export interface LibraryListOptions {
|
||||
open: (key: string, label: string) => void;
|
||||
}
|
||||
|
||||
const SIZE = 30;
|
||||
const why = (error: unknown): string => (error instanceof Error ? error.message : "");
|
||||
const money = (v: number | null | undefined): string =>
|
||||
v == null ? "" : v.toLocaleString("ko-KR", { maximumFractionDigits: 2 });
|
||||
@@ -54,7 +59,10 @@ export function mountLibraryList(
|
||||
): { getDoc: () => null; destroy: () => void } {
|
||||
let rows: Row[] = [];
|
||||
let picked: string | null = null;
|
||||
let page = 1;
|
||||
const searchField = createInputField({ type: "search", placeholder: tc("Search") });
|
||||
const body = el("tbody");
|
||||
let pager = buildPager(0, SIZE, 1, () => {});
|
||||
const btnNew = createButton({ label: tc("Lib_Create"), variant: "filled" });
|
||||
const btnCopy = createButton({ label: tc("Lib_Copy"), variant: "ghost" });
|
||||
const btnDel = createButton({ label: tc("Lib_Delete"), variant: "danger" });
|
||||
@@ -63,9 +71,18 @@ export function mountLibraryList(
|
||||
};
|
||||
|
||||
const draw = (): void => {
|
||||
const q = searchField.input.value.trim().toLowerCase();
|
||||
const shown = rows.filter((r) => !q || libraryLabel(r).toLowerCase().includes(q));
|
||||
page = Math.min(page, Math.max(1, Math.ceil(shown.length / SIZE)));
|
||||
const next = buildPager(shown.length, SIZE, page, (p) => {
|
||||
page = p;
|
||||
draw();
|
||||
});
|
||||
pager.replaceWith(next);
|
||||
pager = next;
|
||||
body.replaceChildren(
|
||||
...(rows.length
|
||||
? rows.map((row) => {
|
||||
...(shown.length
|
||||
? shown.slice((page - 1) * SIZE, page * SIZE).map((row) => {
|
||||
const radio = el("input", {
|
||||
attrs: { type: "radio", name: `m02-lib-${opt.kind}`, "aria-label": row.이름 },
|
||||
}) as HTMLInputElement;
|
||||
@@ -78,7 +95,7 @@ export function mountLibraryList(
|
||||
paintButtons();
|
||||
});
|
||||
const tr = el("tr", {
|
||||
className: "m02-lib__row",
|
||||
className: "m01-master__table-row",
|
||||
attrs: { "data-lib-key": row.이름 },
|
||||
children: [
|
||||
pick,
|
||||
@@ -200,14 +217,19 @@ export function mountLibraryList(
|
||||
}
|
||||
});
|
||||
|
||||
searchField.input.addEventListener("input", () => {
|
||||
page = 1;
|
||||
draw();
|
||||
});
|
||||
const heads = ["", "Lib_Key", "Lib_Name", "Lib_Unit", "Lib_Base", "Lib_Date"] as const;
|
||||
host.replaceChildren(
|
||||
buildHeadFilters([searchField.root, pager]),
|
||||
el("div", {
|
||||
className: "ui-general-block__table-wrap ui-general-block__table-wrap--sticky-head",
|
||||
className: "m01-master__grid-wrap",
|
||||
attrs: { "data-lib-list": opt.kind },
|
||||
children: [
|
||||
el("table", {
|
||||
className: "ui-general-block__table m02-lib__table",
|
||||
className: "m01-master__grid",
|
||||
children: [
|
||||
el("thead", {
|
||||
children: [
|
||||
|
||||
@@ -56,16 +56,8 @@
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
/* 일위대가 조합 서고 목록표(51-4) — 줄 누름 = 상세 · 첫 칸 = 고름 */
|
||||
.m02-lib__row {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.m02-lib__row:hover {
|
||||
background: var(--color-bg-hover, rgba(0, 0, 0, 0.04));
|
||||
}
|
||||
|
||||
.m02-lib__table .m02-lib__pick {
|
||||
/* 일위대가 조합 서고 목록표(51-4) — 표 꼴은 M01 목록(`m01-master__grid`) · 첫 칸 = 고름 */
|
||||
.m01-master__grid .m02-lib__pick {
|
||||
width: 2.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -123,6 +115,7 @@
|
||||
/* 제목 줄 오른쪽 끝 도구(일위대가 「새 조합」 · PLAN 30-5) */
|
||||
.m02-main__tools {
|
||||
display: inline-flex;
|
||||
gap: var(--spacing-8); /* M01 머리 줄(`m01-head`)과 같은 틈 */
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user