/* ============================================================================= * B01_Dashboard_UI_Profile.ts * 내 정보 카드(549-2) — 기본정보(이름 · 직급 · 부서 · 전화 · 이메일 · 서명) · 비밀번호 변경. * 모양 = 설정 줄(제목 · 설명 · 오른쪽 조작) · 저장 길은 옛 폼과 같음(`updateUserProfile` · `changePassword`). * ========================================================================== */ import { isBlank } from "@util/common_util_validate"; import { createButton } from "@ui/ui_template_elements"; import { changePassword, fetchCompanyAssets, updateCompanyAsset, updateUserProfile, type DashboardUser, } from "./B01_Dashboard_Api_Fetch"; import { createAssetField } from "./B01_Dashboard_UI_AssetPicker"; import { L, runRequest } from "./B01_Dashboard_UI_Common"; import { settingCard, settingRow, valueText } from "./B01_Dashboard_UI_PageKit"; import { el } from "./B01_Dashboard_UI_View_Parts"; const PASSWORD_MIN_LENGTH = 8; function input(value: string, type = "text", label = ""): HTMLInputElement { const box = el("input", "b01-sys-input"); box.type = type; box.value = value; if (label) box.ariaLabel = label; return box; } /** 입력 줄 아래에 오류 글 — 비우면 지움 */ function fieldError(row: HTMLElement, message?: string): void { row.querySelector(".b01-sys-error")?.remove(); if (message) row.querySelector(".ui-setting-row__text")?.append(el("span", "b01-sys-error", message)); } export function buildProfileCard(user: DashboardUser): HTMLElement { const name = input(user.name, "text", "이름"); const position = input(user.position ?? "", "text", "직급"); const department = input(user.department ?? "", "text", "부서"); const phone = input(user.phone ?? "", "tel", "전화"); const nameRow = settingRow("이름", "도면 표제란 · 보고서에 들어갑니다.", name); // 본인 서명 — 도면 표제란이 이 사람 자리를 채울 때 그대로 실림(회사 소속일 때만) const signature = el("div", "b01-sys-assetslot"); if (user.company_id) { void fetchCompanyAssets(user.company_id).then((assets) => { const owned = assets.find((a) => a.kind === "SIGNATURE" && a.user_id === user.id); signature.append( createAssetField("서명", "SIGNATURE", assets, owned?.id ?? null, user.company_id!, user, { owner: { id: user.id, name: user.name }, onChange: async (assetId) => { if (assetId === null) return; const picked = assets.find((a) => a.id === assetId); if (picked) await updateCompanyAsset(assetId, { label: picked.label, user_id: user.id }); }, }).root, ); }); } const save = createButton({ label: L("B01_Dashboard_SaveProfile"), onClick: async function onB01_Profile_Save_Click() { fieldError(nameRow); if (!name.value.trim()) return fieldError(nameRow, L("Common_Msg_RequiredField")); await runRequest(() => updateUserProfile({ name: name.value.trim(), position: position.value.trim() || null, department: department.value.trim() || null, phone: phone.value.trim() || null, }), ); }, }); const rows = [ nameRow, settingRow("직급", "", position), settingRow("부서", "", department), settingRow("전화", "", phone), settingRow("이메일", "로그인에 쓰는 계정이라 바꿀 수 없습니다.", valueText(user.email)), ]; if (user.company_id) rows.push(settingRow("서명", "보고서 서명란 · 도면 결재란에 들어갑니다.", signature)); rows.push(settingRow("", "", save)); return settingCard(rows); } /** 비밀번호 — [변경] 을 누르면 입력 줄이 펼쳐짐 */ export function buildPasswordCard(): HTMLElement { const current = input("", "password", "현재 비밀번호"); const next = input("", "password", "새 비밀번호"); const confirm = input("", "password", "새 비밀번호 확인"); const rows = [ settingRow("현재 비밀번호", "", current), settingRow("새 비밀번호", `${PASSWORD_MIN_LENGTH} 자 이상`, next), settingRow("새 비밀번호 확인", "", confirm), ]; const form = el("div"); form.hidden = true; const save = createButton({ label: L("B01_Account_Save_Password"), onClick: async function onB01_Password_Save_Click() { for (const r of rows) fieldError(r); const required = L("Common_Msg_RequiredField"); if (isBlank(current.value)) return fieldError(rows[0], required); if (isBlank(next.value)) return fieldError(rows[1], required); if (isBlank(confirm.value)) return fieldError(rows[2], required); if (next.value.length < PASSWORD_MIN_LENGTH) return fieldError(rows[1], L("B01_Account_Error_PwLength")); if (next.value !== confirm.value) return fieldError(rows[2], L("B01_Account_Error_PwMismatch")); await runRequest(() => changePassword({ current_password: current.value, new_password: next.value, new_password_confirm: confirm.value, logout_all: false, }), ); current.value = next.value = confirm.value = ""; form.hidden = true; }, }); form.append(...rows, settingRow("", "", save)); const toggle = createButton({ label: "변경", variant: "ghost", onClick: () => (form.hidden = !form.hidden), }); return settingCard([settingRow("비밀번호", "주기적으로 바꾸면 안전합니다.", toggle), form]); }