- 위험 채움 토큰 밝음 #e5484d → #d6363c(흰 글 3.91 → 4.72) · 어두움 5.6 · 위험 글 #c0392b 그대로 - 새 부품 계산 줄(ui_template_calc_row) — B08 수리집수면적표 b08-hydro__row · 식 칸 배치를 대신함 - 표 부품 칸 램프(ui-data-table__lamp · --only · ✓) — B08 집계표 · 거리이정표 · B09 설계내역 램프 CSS 세 벌을 걷음(표지 class 는 풍선 · 가이드용으로 남김) - 모달 넓은 중간 창(wide + width 1100px · 1100 × 680) — B09 운반 창 손 인라인 크기를 걷음 - 값 목록 규칙 꼴(rule) — ☰ 설정 규칙 줄 ul/li 를 걷음 - 접이 구역 머리(createCollapsibleHead = 패널 머리 + 접는 제목) — B08 구조물도 「조합 연결」 제목(옛 b08-sheets__title)을 대신함 - 일반 화면 틀 좁은 폭 · 입력 칸 2열 · 끝 단추 줄 — D01 · E01 이 B02 CSS 를 빌리던 것을 끊음(가이드 장면 선택자 맞춤) - 부품 모음 견본 · 지킴 시험 test_557_2 · 낡은 시험(198_1 · 247_1 · 251_1 · 257_1 · 276_1 · 551_1)은 부품 CSS · 새 class 로 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
96 lines
3.4 KiB
TypeScript
96 lines
3.4 KiB
TypeScript
/* =============================================================================
|
|
* E01_StabRegister_UI_Page.ts
|
|
* E01 안정성평가 생성(요구서 345 4-1 · PLAN 528-2) — 대상 임도 고르기(GET /api/e01/source-candidates
|
|
* = 같은 회사 · B06 완료만) · 이름(손대기 전 = 「원본 이름 안정성평가」).
|
|
* [등록] = POST /api/e01/project → 현재 프로젝트 · E02 로.
|
|
* ========================================================================== */
|
|
|
|
import { API_BASE_URL, ROUTES } from "@config/config_frontend";
|
|
import {
|
|
createButton,
|
|
createCard,
|
|
createInputField,
|
|
createSelectField,
|
|
el,
|
|
} from "@ui/ui_template_elements";
|
|
import { createFormGrid, createGeneralLayout } from "@ui/ui_template_general_layout";
|
|
import { createHelpButton } from "@ui/ui_template_help";
|
|
import { t } from "@ui/ui_template_locale";
|
|
import { createGroupProject } from "../A00_Common/group_workflow";
|
|
import { navigateTo } from "../A00_Common/router";
|
|
|
|
interface SourceProject {
|
|
project_id: string;
|
|
name: string;
|
|
region?: string | null;
|
|
project_year?: number | null;
|
|
}
|
|
|
|
export function renderE01StabRegister(root: HTMLElement): void {
|
|
const source = createSelectField({ label: t("DE_Reg_Source"), options: [] });
|
|
const name = createInputField({ label: t("DE_Reg_Name") });
|
|
const note = el("p", { className: "ui-general-block__empty" });
|
|
let sources: SourceProject[] = [];
|
|
let typed = false;
|
|
const autoName = (): string => {
|
|
const picked = sources.find((p) => p.project_id === source.select.value);
|
|
return picked ? `${picked.name} ${t("DE_New_Stability")}` : "";
|
|
};
|
|
name.input.addEventListener("input", () => (typed = name.input.value.trim() !== ""));
|
|
source.select.addEventListener("change", () => {
|
|
if (!typed) name.input.value = autoName();
|
|
});
|
|
|
|
const submitButton = createButton({
|
|
label: t("DE_Reg_Submit"),
|
|
variant: "filled",
|
|
onClick: () => {
|
|
// 목록이 비면 단추가 꺼져 있음 — 고른 값은 늘 있음
|
|
void createGroupProject(
|
|
"/e01/project",
|
|
{ project_name: name.input.value.trim() || null, source_project_id: source.select.value },
|
|
ROUTES.E02_STAB_GROUND,
|
|
);
|
|
},
|
|
});
|
|
submitButton.disabled = true;
|
|
|
|
void (async () => {
|
|
const response = await fetch(`${API_BASE_URL}/e01/source-candidates`, {
|
|
credentials: "include",
|
|
});
|
|
sources = response.ok
|
|
? ((await response.json()) as { projects: SourceProject[] }).projects
|
|
: [];
|
|
source.setOptions(
|
|
sources.map((p) => ({
|
|
value: p.project_id,
|
|
text: [p.name, p.region, p.project_year].filter(Boolean).join(" · "),
|
|
})),
|
|
);
|
|
note.textContent = sources.length ? "" : t("DE_Reg_SourceEmpty");
|
|
submitButton.disabled = !sources.length;
|
|
if (!typed) name.input.value = autoName();
|
|
})();
|
|
|
|
const grid = createFormGrid([source.root, name.root]);
|
|
const actions = document.createElement("div");
|
|
actions.className = "ui-general-block__actions ui-general-block__actions--end";
|
|
actions.append(
|
|
createHelpButton(),
|
|
createButton({
|
|
label: t("Common_Btn_Cancel"),
|
|
variant: "ghost",
|
|
onClick: () => navigateTo(ROUTES.B01_ACCOUNT),
|
|
}),
|
|
submitButton,
|
|
);
|
|
const layout = createGeneralLayout({
|
|
narrow: true,
|
|
title: t("DE_Reg_StabTitle"),
|
|
subtitle: t("DE_Reg_StabSubtitle"),
|
|
content: createCard({ body: [grid, note, actions], raised: true }),
|
|
});
|
|
root.append(layout.root);
|
|
}
|