인증 요청 안정화와 월간 메일 한도 적용
This commit is contained in:
94
script/auth-form.js
Normal file
94
script/auth-form.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 인증 화면 제출 버튼 상태 관리
|
||||
*/
|
||||
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) {
|
||||
throw new Error(data.error || `요청 실패 (${response.status})`);
|
||||
}
|
||||
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;
|
||||
Reference in New Issue
Block a user