Files
Aislo/B01_Dashboard/B01_Dashboard_UI_Profile.ts
T
eomsangdonandClaude Opus 5 2adb5507a4 feat(B01,B02): 팀원 등록 방식 교체·사용자 삭제/비활성화·B02 등록 화면 정비
B01
- 팀원 등록을 계정 대리 생성에서 「소속 없는 기존 가입자 검색·선택」으로 교체, 미가입자는 안내 메일만 발송
- 사용자 계정 삭제 API 신설, 삭제 모달에서 회사 제외/계정 삭제 선택, 관리자 수정 모달에 활성·비활성 상태 지정
- 기본정보 폼과 사용자 수정 폼을 공용 입력칸 한 벌로 통일 (이름 > 직급 > 이메일 > 부서 > 전화)
- 프로젝트 담당자 선택의 신규 등록 항목 제거

B02
- 프로젝트명 자동 조합 (사업연도 + 사업지역 + 임도종류 + 직접 입력값) 및 미리보기 표시
- 예상 연장 입력칸 제거, 노선 종료 누가거리 제목에 구간 연장 표기, 표지 값은 프로젝트명·연장에서 파생
- 취소 버튼 추가 (대시보드 복귀), 담당자 기본값을 생성자로 지정

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-06 11:24:43 +09:00

84 lines
2.9 KiB
TypeScript

import { isBlank } from "@util/common_util_validate";
import { createButton, createInputField } from "@ui/ui_template_elements";
import { changePassword, updateUserProfile, type DashboardUser } from "./B01_Dashboard_Api_Fetch";
import { buildUserFields, L, runRequest } from "./B01_Dashboard_UI_Common";
const PASSWORD_MIN_LENGTH = 8;
export function buildProfileForm(user: DashboardUser): HTMLElement {
const fields = buildUserFields(user);
const grid = fields.grid;
const save = createButton({
label: L("B01_Dashboard_SaveProfile"),
onClick: async function onB01_Profile_Save_Click() {
if (!fields.validate()) return;
await runRequest(() => updateUserProfile(fields.values()));
},
});
const wrap = document.createElement("div");
wrap.append(grid, save);
return wrap;
}
export function buildSecurityForm(): HTMLElement {
const currentPassword = createInputField({
label: L("B01_Account_Field_CurrentPw"),
type: "password",
required: true,
});
const newPassword = createInputField({
label: L("B01_Account_Field_NewPw"),
type: "password",
required: true,
});
const confirmPassword = createInputField({
label: L("B01_Account_Field_ConfirmPw"),
type: "password",
required: true,
});
const grid = document.createElement("div");
grid.className = "b01-dashboard__form-grid";
grid.append(currentPassword.root, newPassword.root, confirmPassword.root);
const save = createButton({
label: L("B01_Account_Save_Password"),
variant: "ghost",
onClick: async function onB01_Password_Save_Click() {
currentPassword.setError();
newPassword.setError();
confirmPassword.setError();
const currentValue = currentPassword.input.value;
const nextValue = newPassword.input.value;
const confirmValue = confirmPassword.input.value;
if (isBlank(currentValue) || isBlank(nextValue) || isBlank(confirmValue)) {
currentPassword.setError(isBlank(currentValue) ? L("Common_Msg_RequiredField") : undefined);
newPassword.setError(isBlank(nextValue) ? L("Common_Msg_RequiredField") : undefined);
confirmPassword.setError(isBlank(confirmValue) ? L("Common_Msg_RequiredField") : undefined);
return;
}
if (nextValue.length < PASSWORD_MIN_LENGTH) {
newPassword.setError(L("B01_Account_Error_PwLength"));
return;
}
if (nextValue !== confirmValue) {
confirmPassword.setError(L("B01_Account_Error_PwMismatch"));
return;
}
await runRequest(() =>
changePassword({
current_password: currentValue,
new_password: nextValue,
new_password_confirm: confirmValue,
logout_all: false,
}),
);
currentPassword.input.value = "";
newPassword.input.value = "";
confirmPassword.input.value = "";
},
});
const wrap = document.createElement("div");
wrap.append(grid, save);
return wrap;
}