Files
Aislo/M01_MasterData/M01_MasterData_UI_LogicLab_Basic.ts
eomsangdonandClaude Opus 5.5 022eff69f5 refactor(M01): 표 · 모달 · 띠 알림 · 배지 · 알약 · 보조 글 · 빈 상태를 부품으로 (PLAN 553-5)
- 표 둘 = 표 부품(m01-master__grid = 일반표 · m01-logic__grid = 데이터표) · 페이지 CSS 는 폭 · 머리 고정 · 칸 상태만
- 손 모달 다섯(조달 찾기 · 요소 고르기 · 표 바꾸기 · 복사 시트 · 표 고르기) = 모달 부품 openModal
- 알림 띠 · 막힘 까닭 = 띠 알림 · 태그 = 배지 · 알약 · × · 삭제 · 로직 키 = 단추 부품 · muted 세 벌 = 보조 글 · 빈 줄 = 빈 상태
- M02 가 빌린 M01 클래스(표 · muted · 고르기 창)도 같은 부품으로 · 죽은 CSS 걷음 · 지킴 시험 test_553_5_m01_m02

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 22:57:33 +09:00

106 lines
3.7 KiB
TypeScript

/* =============================================================================
* M01_MasterData_UI_LogicLab_Basic.ts
* 「신규 로직」 기본정보 칸 — 이름 · 원문번호 · 결과 단위 · 출처(구분 = 자체). 확인하면 값을 돌려줌 · 취소면 null
* 저장은 하지 않음 — 부른 쪽이 빈 흐름도와 함께 캐시(drafts)에 새 줄로 넣고 [저장] 때 서버가 GX 새 키를 줌.
* ========================================================================== */
import { currentLanguageIndex } from "@ui/ui_template_locale";
import { createButton, createInputField, createSelectField, el } from "@ui/ui_template_elements";
import { openModal } from "@ui/ui_template_modal";
const TEXT = {
Title: ["신규 로직", "New logic"],
Name: ["이름", "Name"],
NamePh: ["예: 돌쌓기 메쌓기(인력)", "e.g. dry stone wall (labour)"],
Number: ["원문번호", "Source number"],
NumberPh: ["예: 13-4-1 · 없으면 비움", "e.g. 13-4-1 · may be empty"],
Unit: ["결과 단위", "Result unit"],
Source: ["출처", "Source"],
Ok: ["만들기", "Create"],
Cancel: ["취소", "Cancel"],
Close: ["닫기", "Close"],
NeedName: ["이름을 넣어 주세요", "Enter a name"],
} as const;
const tb = (key: keyof typeof TEXT): string => TEXT[key][currentLanguageIndex === 1 ? 1 : 0];
export interface BasicInfo {
이름: string;
원문번호: string;
결과단위: string;
출처: string;
}
/** 기본정보 묻기 — units = 결과 단위 후보(마스터 로직의 결과단위) */
export function askBasicInfo(units: string[]): Promise<BasicInfo | null> {
return new Promise((resolve) => {
let done = false;
const finish = (v: BasicInfo | null): void => {
if (done) return;
done = true;
resolve(v);
};
const name = createInputField({ label: tb("Name"), placeholder: tb("NamePh"), compact: true });
const number = createInputField({
label: tb("Number"),
placeholder: tb("NumberPh"),
compact: true,
});
const unit = createSelectField({
label: tb("Unit"),
options: units.map((u) => ({ value: u, text: u })),
value: units[0] ?? "원",
compact: true,
});
const source = createInputField({ label: tb("Source"), value: "자체", compact: true });
const why = el("p", { className: "ui-text ui-text--muted", attrs: { role: "alert" } });
const modal = openModal({
title: tb("Title"),
closeLabel: tb("Close"),
beforeClose: () => {
finish(null);
return true;
},
mount: (body, close) => {
const ok = (): void => {
const 이름 = name.input.value.trim();
if (!이름) {
why.textContent = tb("NeedName");
return void name.input.focus();
}
finish({
이름,
원문번호: number.input.value.trim(),
결과단위: unit.select.value,
출처: source.input.value.trim() || "자체",
});
close();
};
name.input.addEventListener("keydown", (ev) => ev.key === "Enter" && ok());
body.append(
name.root,
number.root,
unit.root,
source.root,
why,
el("div", {
className: "ui-toolbar m01-logic__bar",
children: [
createButton({ label: tb("Ok"), size: "sm", onClick: ok }),
createButton({
label: tb("Cancel"),
variant: "ghost",
size: "sm",
onClick: () => {
finish(null);
modal.close();
},
}),
],
}),
);
},
});
});
}