이메일 인증 재발송과 관리자 승인 개선

This commit is contained in:
2026-06-25 16:51:29 +09:00
parent 5fbd58bd07
commit a5b7d720d6
26 changed files with 688 additions and 91 deletions

View File

@@ -61,6 +61,20 @@ const UaDeckApi = (() => {
return data.error || `요청 실패 (${res.status})`;
}
/**
* API 오류 객체 생성
* @param {Response} res
* @param {object} data
* @returns {Error & {status?: number, code?: string, data?: object}}
*/
function createApiError(res, data) {
const error = new Error(formatError(res, data));
error.status = res.status;
error.code = data.code;
error.data = data;
return error;
}
/**
* 저장된 토큰
* @returns {string|null}
@@ -126,7 +140,7 @@ const UaDeckApi = (() => {
const data = await res.json().catch(() => ({}));
if (!res.ok) {
throw new Error(formatError(res, data));
throw createApiError(res, data);
}
return data;
}
@@ -232,6 +246,10 @@ const UaDeckApi = (() => {
adminUpdateUser: (id, body) =>
request(`/admin/users/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
/** @param {number} id */
adminVerifyUserEmail: (id) =>
request(`/admin/users/${id}/verify-email`, { method: 'POST' }),
/** @param {number} id @param {string} newPassword */
adminResetPassword: (id, newPassword) =>
request(`/admin/users/${id}/reset-password`, {

View File

@@ -45,7 +45,11 @@ const UaAuthForm = (() => {
});
const data = await response.json().catch(() => ({}));
if (!response.ok) {
throw new Error(data.error || `요청 실패 (${response.status})`);
const error = new Error(data.error || `요청 실패 (${response.status})`);
error.status = response.status;
error.code = data.code;
error.data = data;
throw error;
}
return data;
}

View File

@@ -2,13 +2,15 @@
* data-i18n 속성 기반 페이지 번역
*/
(function initPageI18n() {
const SUPPORTED_LANGUAGES = new Set(['ko', 'ja', 'en']);
/**
* @returns {Promise<string>}
*/
function getLang() {
const fromQuery = new URLSearchParams(window.location.search).get('lang');
if (fromQuery) return fromQuery;
return localStorage.getItem('lang') || 'ko';
const selected = fromQuery || localStorage.getItem('lang') || 'ko';
return SUPPORTED_LANGUAGES.has(selected) ? selected : 'ko';
}
/**
@@ -59,6 +61,7 @@
async function applyPageI18n() {
const lang = await getLang();
document.documentElement.lang = lang;
cachedTranslations = await loadTranslations(lang);
applyTranslations(cachedTranslations);
return cachedTranslations;