diff --git a/M02_MasterTemplete/CostFlow/M02_CF_Entry.css b/M02_MasterTemplete/CostFlow/M02_CF_Entry.css index a967d85f7..98c3faa23 100644 --- a/M02_MasterTemplete/CostFlow/M02_CF_Entry.css +++ b/M02_MasterTemplete/CostFlow/M02_CF_Entry.css @@ -153,3 +153,39 @@ grid-template-columns: minmax(0, 1fr); } } + +.m02-cf__list { + display: flex; + flex-direction: column; + gap: var(--spacing-4); +} + +.m02-cf__item { + display: flex; + align-items: center; + gap: var(--spacing-8); + width: 100%; + padding: var(--spacing-8) var(--spacing-12); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + background: var(--color-surface); + color: var(--color-text); + font: inherit; + text-align: left; + cursor: pointer; +} + +.m02-cf__item:hover { + border-color: var(--color-accent); +} + +.m02-cf__item-name { + flex: 1; + min-width: 0; +} + +.m02-cf__item-unit { + color: var(--color-text-muted); + font-size: var(--text-body-sm); + white-space: nowrap; +} diff --git a/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts b/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts index c1e8bad94..84e7a2f91 100644 --- a/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts +++ b/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts @@ -18,6 +18,7 @@ import { showToast, } from "@ui/ui_template_elements"; import { fetchLogics } from "../../M01_MasterData/M01_MasterData_UI_Logic_Api"; +import type { CfListItem } from "./M02_CF_Api"; import type { CfLogic } from "./M02_CF_Model"; import "./M02_CF_Entry.css"; @@ -62,6 +63,8 @@ const muted = (text: string): HTMLElement => el("p", { className: "m02-cf__muted /* ponytail: Model(sub7) · Api(sub4) · Sample(sub6) 속이 「준비 중」 인 동안만 대신함 — 채워지면 catch 를 지움 */ const blankLogic = (name: string, unit: string): Promise => import("./M02_CF_Model").then((m) => m.newLogic(name, unit)).catch(() => null); +const loadList = (): Promise => + import("./M02_CF_Api").then((m) => m.cfList()).catch(() => []); /** 결과 단위 후보 — 품셈 로직에 다섯 번 넘게 쓰인 「원/…」 차례(설명 붙은 드문 단위는 뺌) */ async function unitChoices(): Promise { @@ -133,9 +136,34 @@ function openCostFlow(): void { /* ---------- 시작 화면 ---------- */ + const listRow = (item: CfListItem): HTMLElement => { + const row = el("button", { + className: "m02-cf__item", + attrs: { type: "button", title: item.saved }, + children: [ + el("span", { className: "m02-cf__item-name", text: item.name }), + el("span", { className: "m02-cf__item-unit", text: item.resultUnit }), + ], + }); + row.addEventListener("click", () => showToast(te("NotYet"), "info")); + return row; + }; + const showStart = (): void => { paper = null; strip.replaceChildren(); + const mineHost = el("div", { className: "m02-cf__list", children: [muted(te("Loading"))] }); + const sampleHost = el("div", { className: "m02-cf__list", children: [muted(te("Loading"))] }); + void loadList().then((all) => { + const mine = all.filter((x) => !x.sample); + const samples = all.filter((x) => x.sample); + mineHost.replaceChildren( + ...(mine.length ? mine.map(listRow) : [muted(te("Start_MineNone"))]), + ); + sampleHost.replaceChildren( + ...(samples.length ? samples.map(listRow) : [muted(te("Start_MineNone"))]), + ); + }); body.replaceChildren( el("div", { className: "m02-cf__start", @@ -145,12 +173,12 @@ function openCostFlow(): void { children: [ bigButton(te("Start_New"), () => void openNew()), el("h3", { text: te("Start_Mine") }), - muted(te("Start_MineNone")), + mineHost, ], }), el("section", { className: "m02-cf__start-col", - children: [el("h3", { text: te("Start_Samples") }), muted(te("NotYet"))], + children: [el("h3", { text: te("Start_Samples") }), sampleHost], }), ], }),