feat(729-3): 단가산출 못옮김 잇기 창 · 단위 성격 다른 후보 계수 칸 · 남은 줄 표 못옮김 단추(729-4 이음)
- 새 Hopyo_Lost: 못옮김 줄마다 찾기(노임 LB · 자재 MT) · 기계(EQ) · 우리에 없음(뺌) → 캐시 m02-hopyo-lost 모두를 [잇기 만들기] 한 번에(서버가 부를 때마다 그 블록 잇기 전부로 다시 셈) · 바탕 = 그 SK 문서 바탕(로직 · 입력값 · 환산)
- 단가산출 칸: 만든 줄 표 못옮김 열 · [잇기 (n)] · 만든 줄 모아 둠 · 고름 대기 후보 계수(성격 다른 단위) = 계수 칸 → 환산 {계수} · 729-5 남은못옮김 칸 미리 받음
- 안 이은 줄 표: 못옮김 남은 SK 를 쓰는 줄(단산 · SK · 못옮김) = [못옮김 잇기 (n)]
- 시험 test_729_3_hopyo_left_screen 소스 확인 더함(계수 · 잇기 모두 · 바탕)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,14 +3,23 @@
|
||||
* 일위대가 불러오기 마법사 ② 단가산출 단계(PLAN 729-3 · 요구서 내역19 1장 7 · 2장 3) —
|
||||
* · [단가산출 만들기] = 서버 `sangeun`(산근 블록마다 매칭 → 같으면 기초 · 다르면 SK = 기초 + 엑셀 차이 · 맞는 기초 없음 = 고름 대기)
|
||||
* · 만든 줄 표 = 블록 · 이름 · 키 · 갈래(기초 · SK 차이 있음) · 이미 만든 블록은 「그대로」 수만
|
||||
* · 고름 대기 표 = 블록마다 후보(판정 · 글) 고르기 칸 → [고른 기초로 만들기](바탕 = 고른 기초 · 엑셀 품 견줘 SK)
|
||||
* · 고름 대기 표 = 블록마다 후보(판정 · 글) 고르기 칸 → [고른 기초로 만들기](바탕 = 고른 기초 · 엑셀 품 견줘 SK) ·
|
||||
* 단위 성격 다른 후보(729-4 `계수`) = 계수 칸(가 1 = 나 몇) 함께 → `환산 {계수}`
|
||||
* · 못옮김(729-4) = 만든 줄마다 수 · [잇기] = 못옮김 잇기 창(`Hopyo_Lost`) · 만든 줄은 이 칸이 모아 둠(누를 때마다 더함) ·
|
||||
* 이미 만든 SK 의 남은 못옮김(729-5 `남은못옮김`)도 같은 표
|
||||
* · 별칭 제안 = 이 층 별칭 장부에 남음 · 모두에게 쓰이려면 시스템 관리자가 M01 › 별칭 장부에서 승인(링크 · 716 길 그대로)
|
||||
* 계산 · 판정은 서버 — 화면은 보이기 · 고름만 · 자동 저장 없음(누를 때만 서버).
|
||||
* ========================================================================== */
|
||||
|
||||
import { ROUTES } from "@config/config_frontend";
|
||||
import { createBadge } from "@ui/ui_template_badge";
|
||||
import { createButton, createSelectField, el, showToast } from "@ui/ui_template_elements";
|
||||
import {
|
||||
createButton,
|
||||
createInputField,
|
||||
createSelectField,
|
||||
el,
|
||||
showToast,
|
||||
} from "@ui/ui_template_elements";
|
||||
import { t as L } from "@ui/ui_template_locale";
|
||||
import { createTable } from "@ui/ui_template_table";
|
||||
import { createText } from "@ui/ui_template_text";
|
||||
@@ -20,6 +29,9 @@ import {
|
||||
type SangeunBuilt,
|
||||
type SangeunPick,
|
||||
} from "./M02_MasterTemplete_Hopyo_Api";
|
||||
import { openLost } from "./M02_MasterTemplete_Hopyo_Lost";
|
||||
|
||||
type Made = SangeunBuilt["만듦"][number];
|
||||
|
||||
const why = (error: unknown): string => (error instanceof Error ? error.message : String(error));
|
||||
|
||||
@@ -48,6 +60,7 @@ export function sangeunStep(scope: HopyoScope, key: string): { root: HTMLElement
|
||||
children: [el("div", { className: "ui-toolbar", children: [make] }), out],
|
||||
});
|
||||
|
||||
const made = new Map<number, Made>(); // 이 칸에서 만든 줄(누를 때마다 더함)
|
||||
async function run(picks?: SangeunPick): Promise<void> {
|
||||
make.disabled = true;
|
||||
try {
|
||||
@@ -69,18 +82,39 @@ export function sangeunStep(scope: HopyoScope, key: string): { root: HTMLElement
|
||||
.replace("{keep}", String(got.그대로))
|
||||
.replace("{wait}", String(got.고름대기.length));
|
||||
|
||||
/** 못옮김 칸 — 수 + [잇기](남은 것 있을 때) */
|
||||
const lostCell = (x: Made, got: SangeunBuilt): HTMLElement => {
|
||||
const n = x.못옮김?.length ?? 0;
|
||||
if (!n) return el("span", { text: "0" });
|
||||
const go = createButton({
|
||||
label: `${L("M02_LostOpen")} (${n})`,
|
||||
size: 24,
|
||||
onClick: () =>
|
||||
openLost({ scope, key, 번: x.번, sk: x.키, 이름: x.이름, lost: x.못옮김 ?? [],
|
||||
done: (next) => draw({ ...got, 만듦: next.만듦, 별칭: got.별칭 }) }), // prettier-ignore
|
||||
});
|
||||
go.dataset.wizLost = String(x.번);
|
||||
return go;
|
||||
};
|
||||
|
||||
function draw(got: SangeunBuilt): void {
|
||||
const made = createTable(
|
||||
for (const x of got.남은못옮김 ?? []) if (!made.has(x.번)) made.set(x.번, { ...x, 갈래: "SK" });
|
||||
for (const x of got.만듦) made.set(x.번, x);
|
||||
const table = createTable(
|
||||
[
|
||||
{ label: L("M02_WizSkBlock"), width: "80px" },
|
||||
{ label: L("M02_SangeunColName") },
|
||||
{ label: L("M02_WizSkKey"), width: "110px" },
|
||||
{ label: L("M02_WizSkKind"), width: "120px" },
|
||||
{ label: L("M02_LostCol"), width: "120px" },
|
||||
],
|
||||
got.만듦.map((x) => [`단산${x.번}`, x.이름, x.키, kindBadge(x.갈래)]),
|
||||
[...made.values()]
|
||||
.sort((a, b) => a.번 - b.번)
|
||||
.map((x) => [`단산${x.번}`, x.이름, x.키, kindBadge(x.갈래), lostCell(x, got)]),
|
||||
{ density: "data", empty: L("M02_WizSkNoneMade") },
|
||||
);
|
||||
const selects = new Map<number, HTMLSelectElement>();
|
||||
const coefs = new Map<number, HTMLInputElement>();
|
||||
const wait = createTable(
|
||||
[
|
||||
{ label: L("M02_WizSkBlock"), width: "80px" },
|
||||
@@ -100,7 +134,18 @@ export function sangeunStep(scope: HopyoScope, key: string): { root: HTMLElement
|
||||
});
|
||||
pick.select.dataset.wizWait = String(x.번);
|
||||
selects.set(x.번, pick.select);
|
||||
return [`단산${x.번}`, x.이름, x.단위 ?? "", x.까닭, pick.root];
|
||||
const coef = createInputField({ type: "number", min: 0, compact: true, size: 24,
|
||||
placeholder: L("M02_WizSkCoef") }); // prettier-ignore
|
||||
coef.input.dataset.wizCoef = String(x.번);
|
||||
const need = (): void => {
|
||||
const c = x.후보.find((y) => y.로직 === pick.select.value)?.계수;
|
||||
coef.root.hidden = !c;
|
||||
coef.input.title = c ? `${c.가} 1 = ${c.나} ?` : "";
|
||||
};
|
||||
pick.select.addEventListener("change", need);
|
||||
need();
|
||||
coefs.set(x.번, coef.input);
|
||||
return [`단산${x.번}`, x.이름, x.단위 ?? "", x.까닭, el("div", { className: "ui-toolbar", children: [pick.root, coef.root] })]; // prettier-ignore
|
||||
}),
|
||||
{ density: "data", empty: L("M02_WizSkNoWait") },
|
||||
);
|
||||
@@ -110,7 +155,13 @@ export function sangeunStep(scope: HopyoScope, key: string): { root: HTMLElement
|
||||
size: 28,
|
||||
onClick: () => {
|
||||
const picks: SangeunPick = {};
|
||||
for (const [no, s] of selects) if (s.value) picks[no] = { 로직: s.value };
|
||||
for (const [no, s] of selects) {
|
||||
if (!s.value) continue;
|
||||
const c = Number(coefs.get(no)?.value);
|
||||
const need = got.고름대기.find((x) => x.번 === no)?.후보.find((y) => y.로직 === s.value)?.계수; // prettier-ignore
|
||||
if (need && !(c > 0)) return showToast(L("M02_WizSkCoefNeed").replace("{n}", String(no)), "warning"); // prettier-ignore
|
||||
picks[no] = { 로직: s.value, ...(need ? { 환산: { 계수: c } } : {}) };
|
||||
}
|
||||
if (!Object.keys(picks).length) return showToast(L("M02_WizSkPickFirst"), "warning");
|
||||
void run(picks);
|
||||
},
|
||||
@@ -123,7 +174,7 @@ export function sangeunStep(scope: HopyoScope, key: string): { root: HTMLElement
|
||||
});
|
||||
out.replaceChildren(
|
||||
createText(summary(got), "muted", 14),
|
||||
made,
|
||||
table,
|
||||
...(got.고름대기.length
|
||||
? [
|
||||
createText(L("M02_WizSkWaitHint"), "hint", 14),
|
||||
|
||||
Reference in New Issue
Block a user