feat(M01): 로직 개선 시험 알약에서 마스터 화면으로 잇기 · 단가 없는 재료 알약에 이유 한 마디 (PLAN 5-3 · 5-4)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PAdA5ThqmtVSsbzjusk1cJ
This commit is contained in:
2026-09-22 00:09:49 +09:00
co-authored by Claude Sonnet 5
parent 6cb6baabd6
commit fc6bb7240e
4 changed files with 81 additions and 3 deletions
+44 -1
View File
@@ -20,7 +20,7 @@ import { createWorkflowOverlays } from "@ui/ui_template_overlay";
import { ROUTES } from "@config/config_frontend";
import { navigateTo } from "../A00_Common/router";
import { fetchSessionUser } from "../A06_Login/A06_Login_Api_Fetch";
import { saveFiles } from "./M01_MasterData_Api_Fetch";
import { saveFiles, type FileInfo } from "./M01_MasterData_Api_Fetch";
import { discard, isStale, onDraftChange, payload, totalCount } from "./M01_MasterData_Draft";
import { renderRows } from "./M01_MasterData_UI_Rows";
import {
@@ -28,10 +28,14 @@ import {
fileLabel,
loadView,
saveView,
setMasterJump,
setPendingLogicKey,
takePendingLogicKey,
type MasterJump,
type Pick,
} from "./M01_MasterData_UI_Side";
import { loadTable } from "./M01_MasterData_UI_Logic_Note";
import { tl } from "./M01_MasterData_UI_LogicLab_Text";
import { renderTables } from "./M01_MasterData_UI_Tables";
import type { LogicHandle } from "./M01_MasterData_UI_Logic_Page";
import type { ComboHandle } from "./M01_MasterData_UI_Combo";
@@ -227,6 +231,45 @@ function buildPage(): HTMLElement {
});
};
/** 알약 → 마스터 화면 — 찾기 글을 그 키로 두고 열고, 알림줄에 「시험으로 돌아가기」를 둠 */
const jump = async (target: MasterJump): Promise<void> => {
let group = target.kind === "element" ? target.group : "";
let file: FileInfo | undefined;
let ref = "";
if (target.kind === "table") {
const table = await loadTable(target.key);
group =
["소요량", "계수"].find((g) => side.files(g).some((f) => f.file === table?.file)) ?? "";
file = side.files(group).find((f) => f.file === table?.file);
ref = target.key;
} else {
const list = side.files(group);
file = list.find((f) => f.file === target.file) ?? list[0];
ref = target.ref;
}
if (!file) return showToast(L("M01_LoadFailed"), "error");
side.setActive(null);
openFile({ group, file, sub: "", detail: "", label: group, view: { q: ref, page: 1 } });
const back = createButton({ label: tl("Pill_Back"), variant: "ghost" });
back.addEventListener("click", () => {
showNotice([]);
openLabTab();
});
showNotice([back]);
if (target.kind === "table") {
const key = target.key;
const seen = new MutationObserver(() => {
const row = body.querySelector<HTMLElement>(`[data-key="${CSS.escape(key)}"]`);
if (!row) return;
seen.disconnect();
row.click();
});
seen.observe(body, { childList: true, subtree: true });
window.setTimeout(() => seen.disconnect(), 8000);
}
};
setMasterJump((target) => void jump(target));
/* --- 좌측: 컨테이너 --- */
const side = buildSide(openFile, () => openLogicTab(), openLabTab, openComboTab);