260706_1_계정, 로그인, 보안 초안 작성
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import { ROUTES } from "@config/config_frontend";
|
||||
import { isBlank, isValidEmail } from "@util/common_util_validate";
|
||||
import {
|
||||
createButton,
|
||||
createInputField,
|
||||
hideLoadingOverlay,
|
||||
showLoadingOverlay,
|
||||
showToast,
|
||||
} from "@ui/ui_template_elements";
|
||||
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
|
||||
import { navigateTo } from "../A00_Common/router";
|
||||
import { requestLogin, verifyLogin } from "./A06_Login_Api_Fetch";
|
||||
import "./A06_Login_UI_Style.css";
|
||||
|
||||
const L = (key: keyof typeof ui_locales): string => ui_locales[key][currentLanguageIndex];
|
||||
|
||||
export function renderA06Login(root: HTMLElement): void {
|
||||
const page = document.createElement("div");
|
||||
page.className = "a06-login";
|
||||
const card = document.createElement("div");
|
||||
card.className = "a06-login__card";
|
||||
const title = document.createElement("h1");
|
||||
title.className = "a06-login__title";
|
||||
title.textContent = L("A06_Login_Title");
|
||||
const email = createInputField({ label: L("A06_Login_Field_Email"), type: "email" });
|
||||
const password = createInputField({ label: L("A06_Login_Field_Password"), type: "password" });
|
||||
const otp = createInputField({ label: L("A06_Login_Field_Otp"), type: "text" });
|
||||
otp.root.hidden = true;
|
||||
const submit = createButton({ label: L("A06_Login_Submit"), type: "submit" });
|
||||
const form = document.createElement("form");
|
||||
form.className = "a06-login__form";
|
||||
let otpRequired = false;
|
||||
|
||||
async function onA06_Login_Submit_Click(event: Event): Promise<void> {
|
||||
event.preventDefault();
|
||||
const emailValue = email.input.value.trim();
|
||||
if (isBlank(emailValue) || !isValidEmail(emailValue)) {
|
||||
email.setError(L("A06_Login_Error_Email"));
|
||||
return;
|
||||
}
|
||||
if (
|
||||
(!otpRequired && isBlank(password.input.value)) ||
|
||||
(otpRequired && !/^\d{6}$/.test(otp.input.value))
|
||||
) {
|
||||
showToast(L("A06_Login_Error_Required"), "error");
|
||||
return;
|
||||
}
|
||||
showLoadingOverlay();
|
||||
try {
|
||||
const result = otpRequired
|
||||
? await verifyLogin(emailValue, otp.input.value)
|
||||
: await requestLogin(emailValue, password.input.value);
|
||||
if (result.status === "otp_required") {
|
||||
otpRequired = true;
|
||||
otp.root.hidden = false;
|
||||
password.root.hidden = true;
|
||||
submit.querySelector(".ui-btn__label")!.textContent = L("A06_Login_Verify");
|
||||
showToast(L("A06_Login_OtpSent"), "info");
|
||||
} else {
|
||||
showToast(L("A06_Login_Success"), "success");
|
||||
navigateTo(ROUTES.B01_ACCOUNT);
|
||||
}
|
||||
} catch (error) {
|
||||
showToast(error instanceof Error ? error.message : L("A06_Login_Error_Request"), "error");
|
||||
} finally {
|
||||
hideLoadingOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
form.addEventListener("submit", onA06_Login_Submit_Click);
|
||||
form.append(email.root, password.root, otp.root, submit);
|
||||
const register = createButton({
|
||||
label: L("A06_Login_ToRegister"),
|
||||
variant: "ghost",
|
||||
onClick: () => navigateTo(ROUTES.A07_REGISTER),
|
||||
});
|
||||
card.append(title, form, register);
|
||||
page.append(card);
|
||||
root.append(page);
|
||||
}
|
||||
Reference in New Issue
Block a user