99 lines
3.2 KiB
JavaScript
99 lines
3.2 KiB
JavaScript
/**
|
|
* 인증 화면 제출 버튼 상태 관리
|
|
*/
|
|
const UaAuthForm = (() => {
|
|
/**
|
|
* 버튼 로딩 상태 전환
|
|
* @param {HTMLButtonElement} button
|
|
* @param {boolean} loading
|
|
* @param {string} [loadingText='처리 중...']
|
|
*/
|
|
function setLoading(button, loading, loadingText = '처리 중...') {
|
|
if (!button) return;
|
|
if (!button.dataset.idleLabel) {
|
|
button.dataset.idleLabel = button.textContent.trim();
|
|
}
|
|
|
|
button.disabled = loading;
|
|
button.setAttribute('aria-busy', String(loading));
|
|
if (loading) {
|
|
button.classList.add('cursor-wait', 'opacity-70');
|
|
button.innerHTML = `
|
|
<span class="inline-flex items-center justify-center gap-2">
|
|
<span class="size-4 animate-spin rounded-full border-2 border-current/30 border-t-current" aria-hidden="true"></span>
|
|
<span>${loadingText}</span>
|
|
</span>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
button.classList.remove('cursor-wait', 'opacity-70');
|
|
button.textContent = button.dataset.idleLabel;
|
|
}
|
|
|
|
/**
|
|
* 캐시된 구 API 클라이언트에 메서드가 없을 때 인증 API 직접 요청
|
|
* @param {string} path
|
|
* @param {object} body
|
|
* @returns {Promise<object>}
|
|
*/
|
|
async function request(path, body) {
|
|
const response = await fetch(`${UaDeckApi.getBaseUrl()}${path}`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(body),
|
|
});
|
|
const data = await response.json().catch(() => ({}));
|
|
if (!response.ok) {
|
|
const error = new Error(data.error || `요청 실패 (${response.status})`);
|
|
error.status = response.status;
|
|
error.code = data.code;
|
|
error.data = data;
|
|
throw error;
|
|
}
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* 메일 전송 버튼 재요청 대기 표시
|
|
* @param {HTMLButtonElement} button
|
|
* @param {number} seconds
|
|
* @param {string} label
|
|
*/
|
|
function startCooldown(button, seconds, label) {
|
|
setLoading(button, false);
|
|
let remaining = seconds;
|
|
button.disabled = true;
|
|
button.classList.add('cursor-wait', 'opacity-70');
|
|
button.textContent = `${label} (${remaining}초)`;
|
|
|
|
const timer = window.setInterval(() => {
|
|
remaining -= 1;
|
|
if (remaining <= 0) {
|
|
window.clearInterval(timer);
|
|
button.disabled = false;
|
|
button.classList.remove('cursor-wait', 'opacity-70');
|
|
button.textContent = button.dataset.idleLabel;
|
|
return;
|
|
}
|
|
button.textContent = `${label} (${remaining}초)`;
|
|
}, 1000);
|
|
}
|
|
|
|
/**
|
|
* 성공 후 버튼을 완료 상태로 고정
|
|
* @param {HTMLButtonElement} button
|
|
* @param {string} label
|
|
*/
|
|
function setComplete(button, label) {
|
|
setLoading(button, false);
|
|
button.disabled = true;
|
|
button.classList.add('opacity-70');
|
|
button.textContent = label;
|
|
}
|
|
|
|
return { setLoading, request, startCooldown, setComplete };
|
|
})();
|
|
|
|
window.UaAuthForm = UaAuthForm;
|