211 lines
6.4 KiB
JavaScript
211 lines
6.4 KiB
JavaScript
// js/change-password.js
|
|
// 개인 비밀번호 변경 페이지 JavaScript
|
|
|
|
import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js';
|
|
|
|
// 인증 확인
|
|
const token = ensureAuthenticated();
|
|
|
|
// DOM 요소
|
|
const form = document.getElementById('changePasswordForm');
|
|
const messageArea = document.getElementById('message-area');
|
|
const submitBtn = document.getElementById('submitBtn');
|
|
const resetBtn = document.getElementById('resetBtn');
|
|
|
|
// 비밀번호 토글 기능
|
|
document.querySelectorAll('.password-toggle').forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
const targetId = this.getAttribute('data-target');
|
|
const input = document.getElementById(targetId);
|
|
|
|
if (input) {
|
|
const isPassword = input.type === 'password';
|
|
input.type = isPassword ? 'text' : 'password';
|
|
this.textContent = isPassword ? '👁️🗨️' : '👁️';
|
|
}
|
|
});
|
|
});
|
|
|
|
// 초기화 버튼
|
|
resetBtn?.addEventListener('click', () => {
|
|
form.reset();
|
|
clearMessages();
|
|
document.getElementById('passwordStrength').innerHTML = '';
|
|
});
|
|
|
|
// 메시지 표시 함수
|
|
function showMessage(type, message) {
|
|
messageArea.innerHTML = `
|
|
<div class="message-box ${type}">
|
|
${type === 'error' ? '❌' : '✅'} ${message}
|
|
</div>
|
|
`;
|
|
|
|
// 에러 메시지는 5초 후 자동 제거
|
|
if (type === 'error') {
|
|
setTimeout(clearMessages, 5000);
|
|
}
|
|
}
|
|
|
|
function clearMessages() {
|
|
messageArea.innerHTML = '';
|
|
}
|
|
|
|
// 비밀번호 강도 체크
|
|
async function checkPasswordStrength(password) {
|
|
if (!password) {
|
|
document.getElementById('passwordStrength').innerHTML = '';
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const res = await fetch(`${API}/auth/check-password-strength`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ password })
|
|
});
|
|
|
|
const result = await res.json();
|
|
updatePasswordStrengthUI(result);
|
|
} catch (error) {
|
|
console.error('Password strength check error:', error);
|
|
}
|
|
}
|
|
|
|
// 비밀번호 강도 UI 업데이트
|
|
function updatePasswordStrengthUI(strength) {
|
|
const container = document.getElementById('passwordStrength');
|
|
if (!container) return;
|
|
|
|
const colors = {
|
|
0: '#f44336',
|
|
1: '#ff9800',
|
|
2: '#ffc107',
|
|
3: '#4caf50',
|
|
4: '#2196f3'
|
|
};
|
|
|
|
const strengthText = strength.strengthText || '비밀번호를 입력하세요';
|
|
const color = colors[strength.strength] || '#ccc';
|
|
const percentage = (strength.score / strength.maxScore) * 100;
|
|
|
|
container.innerHTML = `
|
|
<div style="margin-top: 12px;">
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;">
|
|
<span style="font-size: 0.85rem; color: ${color}; font-weight: 500;">
|
|
${strengthText}
|
|
</span>
|
|
<span style="font-size: 0.8rem; color: #666;">
|
|
${strength.score}/${strength.maxScore}
|
|
</span>
|
|
</div>
|
|
<div style="height: 6px; background: #e0e0e0; border-radius: 3px; overflow: hidden;">
|
|
<div style="width: ${percentage}%; height: 100%; background: ${color}; transition: all 0.3s;"></div>
|
|
</div>
|
|
${strength.feedback && strength.feedback.length > 0 ? `
|
|
<ul style="margin-top: 10px; font-size: 0.8rem; color: #666; padding-left: 20px;">
|
|
${strength.feedback.map(f => `<li>${f}</li>`).join('')}
|
|
</ul>
|
|
` : ''}
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// 비밀번호 입력 이벤트
|
|
let strengthCheckTimer;
|
|
document.getElementById('newPassword')?.addEventListener('input', (e) => {
|
|
clearTimeout(strengthCheckTimer);
|
|
strengthCheckTimer = setTimeout(() => {
|
|
checkPasswordStrength(e.target.value);
|
|
}, 300);
|
|
});
|
|
|
|
// 폼 제출
|
|
form?.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
clearMessages();
|
|
|
|
const currentPassword = document.getElementById('currentPassword').value;
|
|
const newPassword = document.getElementById('newPassword').value;
|
|
const confirmPassword = document.getElementById('confirmPassword').value;
|
|
|
|
// 유효성 검사
|
|
if (!currentPassword || !newPassword || !confirmPassword) {
|
|
showMessage('error', '모든 필드를 입력해주세요.');
|
|
return;
|
|
}
|
|
|
|
if (newPassword !== confirmPassword) {
|
|
showMessage('error', '새 비밀번호가 일치하지 않습니다.');
|
|
return;
|
|
}
|
|
|
|
if (newPassword.length < 6) {
|
|
showMessage('error', '비밀번호는 최소 6자 이상이어야 합니다.');
|
|
return;
|
|
}
|
|
|
|
if (currentPassword === newPassword) {
|
|
showMessage('error', '새 비밀번호는 현재 비밀번호와 달라야 합니다.');
|
|
return;
|
|
}
|
|
|
|
// 버튼 상태 변경
|
|
const originalText = submitBtn.innerHTML;
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<span>⏳</span><span>처리 중...</span>';
|
|
|
|
try {
|
|
const res = await fetch(`${API}/auth/change-password`, {
|
|
method: 'POST',
|
|
headers: getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
currentPassword,
|
|
newPassword
|
|
})
|
|
});
|
|
|
|
const result = await res.json();
|
|
|
|
if (res.ok && result.success) {
|
|
showMessage('success', '비밀번호가 성공적으로 변경되었습니다.');
|
|
form.reset();
|
|
document.getElementById('passwordStrength').innerHTML = '';
|
|
|
|
// 카운트다운 시작
|
|
let countdown = 3;
|
|
const countdownInterval = setInterval(() => {
|
|
showMessage('success',
|
|
`비밀번호가 변경되었습니다. ${countdown}초 후 로그인 페이지로 이동합니다.`
|
|
);
|
|
countdown--;
|
|
|
|
if (countdown < 0) {
|
|
clearInterval(countdownInterval);
|
|
localStorage.removeItem('token');
|
|
localStorage.removeItem('user');
|
|
window.location.href = '/index.html';
|
|
}
|
|
}, 1000);
|
|
|
|
} else {
|
|
const errorMessage = result.error || '비밀번호 변경에 실패했습니다.';
|
|
showMessage('error', errorMessage);
|
|
}
|
|
} catch (error) {
|
|
console.error('Password change error:', error);
|
|
showMessage('error', '서버와의 연결에 실패했습니다. 잠시 후 다시 시도해주세요.');
|
|
} finally {
|
|
submitBtn.disabled = false;
|
|
submitBtn.innerHTML = originalText;
|
|
}
|
|
});
|
|
|
|
// 페이지 로드 시 현재 사용자 정보 표시
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const user = JSON.parse(localStorage.getItem('user') || '{}');
|
|
console.log('🔐 비밀번호 변경 페이지 로드됨');
|
|
console.log('👤 현재 사용자:', user.username || 'Unknown');
|
|
}); |