327 lines
8.5 KiB
JavaScript
327 lines
8.5 KiB
JavaScript
/* =========================
|
|
전역 상태값
|
|
========================= */
|
|
let isIdChecked = false;
|
|
let checkedUserId = '';
|
|
let isPhoneVerified = false;
|
|
let authTimer = null;
|
|
|
|
const REGEX = {
|
|
id: /^[a-zA-Z][a-zA-Z0-9]{3,11}$/,
|
|
password: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/,
|
|
name: /^[가-힣a-zA-Z\s]+$/,
|
|
phone: /^\d{3}-\d{4}-\d{4}$/
|
|
};
|
|
|
|
/* =========================
|
|
DOM 로드 후 초기화
|
|
========================= */
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initMemberType();
|
|
initEmailDomain();
|
|
initIdCheck();
|
|
initPhoneAuth();
|
|
initFormSubmit();
|
|
initPasswordValidation(); // 비밀번호 규칙
|
|
initNameValidation(); // 이름 특수문자 차단
|
|
initPhoneFormat(); // 휴대폰 자동 하이픈
|
|
// initFormValidation(); // submit 최종 검증
|
|
});
|
|
|
|
/* =========================
|
|
1. 회원유형
|
|
========================= */
|
|
function initMemberType() {
|
|
const radios = document.querySelectorAll('input[name="memberType"]');
|
|
const companyRow = document.querySelector('.company-group');
|
|
|
|
radios.forEach(radio => {
|
|
radio.addEventListener('change', () => {
|
|
if (radio.value === '1') {
|
|
companyRow.style.display = '';
|
|
} else {
|
|
companyRow.style.display = 'none';
|
|
companyRow.querySelectorAll('input').forEach(i => i.value = '');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/* =========================
|
|
2. 이메일 도메인
|
|
========================= */
|
|
function initEmailDomain() {
|
|
const select = document.getElementById('domain_list');
|
|
const custom = document.getElementById('custom_domain');
|
|
|
|
select.addEventListener('change', () => {
|
|
if (select.value === 'type') {
|
|
custom.classList.remove('d-none');
|
|
custom.required = true;
|
|
} else {
|
|
custom.classList.add('d-none');
|
|
custom.required = false;
|
|
custom.value = '';
|
|
}
|
|
});
|
|
}
|
|
|
|
/* =========================
|
|
3. 아이디 중복확인
|
|
========================= */
|
|
function initIdCheck() {
|
|
const input = document.getElementById('user_id');
|
|
const btn = document.getElementById('btn_id_check');
|
|
|
|
if (!btn || !input) {
|
|
console.error('ID input 또는 중복확인 버튼 없음');
|
|
return;
|
|
}
|
|
|
|
// ✅ 아이디 입력값 변경 시 → 중복확인 무효화
|
|
input.addEventListener('input', () => {
|
|
isIdChecked = false;
|
|
checkedUserId = '';
|
|
input.readOnly = false;
|
|
});
|
|
|
|
btn.addEventListener('click', async (e) => {
|
|
e.preventDefault(); // ⭐ 중요 (폼 submit 방지)
|
|
|
|
const userId = input.value.trim();
|
|
|
|
if (!/^[a-zA-Z][a-zA-Z0-9]{3,11}$/.test(userId)) {
|
|
alert('아이디 형식이 올바르지 않습니다.');
|
|
return;
|
|
}
|
|
|
|
const res = await fetch('/kngil/bbs/join.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
action: 'check_id',
|
|
userId: userId
|
|
})
|
|
});
|
|
|
|
const data = await res.json();
|
|
|
|
if (data.available === true) {
|
|
alert('사용 가능한 아이디입니다.');
|
|
|
|
isIdChecked = true;
|
|
checkedUserId = userId;
|
|
|
|
// UX: 아이디 수정 못 하게
|
|
input.readOnly = true;
|
|
} else {
|
|
alert(data.message || '이미 사용 중인 아이디입니다.');
|
|
|
|
isIdChecked = false;
|
|
checkedUserId = '';
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
4. 휴대폰 인증번호
|
|
========================= */
|
|
function initPhoneAuth() {
|
|
const btn = document.querySelector('.btn-code');
|
|
const phoneInput = document.getElementById('user_phone');
|
|
const timerEl = document.querySelector('.timer');
|
|
|
|
btn.addEventListener('click', async () => {
|
|
const phone = phoneInput.value.trim();
|
|
if (!/^\d{3}-\d{4}-\d{4}$/.test(phone)) {
|
|
alert('휴대폰 번호 형식이 올바르지 않습니다.');
|
|
return;
|
|
}
|
|
|
|
await fetch('/api/send_sms.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ phone })
|
|
});
|
|
|
|
startTimer(timerEl, 180);
|
|
alert('인증번호가 발송되었습니다.');
|
|
});
|
|
}
|
|
|
|
function startTimer(el, seconds) {
|
|
clearInterval(authTimer);
|
|
el.classList.remove('d-none');
|
|
|
|
let remain = seconds;
|
|
authTimer = setInterval(() => {
|
|
const m = String(Math.floor(remain / 60)).padStart(2, '0');
|
|
const s = String(remain % 60).padStart(2, '0');
|
|
el.textContent = `${m}:${s}`;
|
|
remain--;
|
|
|
|
if (remain < 0) {
|
|
clearInterval(authTimer);
|
|
el.textContent = '만료';
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
/* =========================
|
|
5. 비밀번호 검증
|
|
========================= */
|
|
function validatePassword() {
|
|
const pw = document.getElementById('user_password').value;
|
|
const pw2 = document.getElementById('user_password_confirm').value;
|
|
|
|
if (!PASSWORD_REGEX.test(pw)) {
|
|
alert('비밀번호는 영문, 숫자, 특수기호를 포함한 8자 이상이어야 합니다.');
|
|
return false;
|
|
}
|
|
|
|
if (pw !== pw2) {
|
|
alert('비밀번호가 일치하지 않습니다.');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* =========================
|
|
6. 가입하기 submit
|
|
========================= */
|
|
function initFormSubmit() {
|
|
const form = document.forms.joinForm;
|
|
|
|
form.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
|
|
if (!isIdChecked) {
|
|
alert('아이디 중복확인을 해주세요.');
|
|
return;
|
|
}
|
|
|
|
if (!validatePassword()) return;
|
|
|
|
const formData = new FormData(form);
|
|
|
|
const email =
|
|
formData.get('userEmail') + '@' +
|
|
(formData.get('emailDomain') === 'type'
|
|
? formData.get('customDomain')
|
|
: formData.get('emailDomain'));
|
|
|
|
const payload = {
|
|
memberType: formData.get('memberType'),
|
|
userId: formData.get('userId'),
|
|
password: formData.get('userPassword'),
|
|
userName: formData.get('userName'),
|
|
email,
|
|
phone: formData.get('userPhone'),
|
|
company: formData.get('companyName'),
|
|
department: formData.get('departmentName')
|
|
};
|
|
|
|
const res = await fetch('/kngil/bbs/join.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload)
|
|
});
|
|
|
|
const data = await res.json();
|
|
|
|
if (data.success) {
|
|
form.style.display = 'none';
|
|
document.querySelector('.messages').style.display = 'block';
|
|
} else {
|
|
alert(data.message);
|
|
}
|
|
});
|
|
}
|
|
|
|
/* =========================
|
|
회원 가입 유효성 체크
|
|
========================= */
|
|
function initPasswordValidation() {
|
|
const pw = document.getElementById('user_password');
|
|
const pw2 = document.getElementById('user_password_confirm');
|
|
const msg = document.getElementById('password_help');
|
|
|
|
function validate() {
|
|
if (!pw.value) return;
|
|
|
|
if (!PASSWORD_REGEX.test(pw.value)) {
|
|
msg.textContent = '영문 + 숫자 + 특수기호 포함 8자 이상';
|
|
msg.classList.remove('success');
|
|
msg.classList.add('error');
|
|
return;
|
|
}
|
|
|
|
if (pw2.value && pw.value !== pw2.value) {
|
|
msg.textContent = '비밀번호가 일치하지 않습니다.';
|
|
msg.classList.remove('success');
|
|
msg.classList.add('error');
|
|
return;
|
|
}
|
|
|
|
msg.textContent = '사용 가능한 비밀번호입니다.';
|
|
msg.classList.remove('error');
|
|
msg.classList.add('success');
|
|
}
|
|
|
|
pw.addEventListener('input', validate);
|
|
pw2.addEventListener('input', validate);
|
|
}
|
|
|
|
|
|
// function initFormValidation() {
|
|
// const form = document.forms.joinForm;
|
|
|
|
// form.addEventListener('submit', e => {
|
|
// e.preventDefault();
|
|
|
|
// const id = form.userId.value.trim();
|
|
// const pw = form.userPassword.value;
|
|
// const pw2 = form.userPasswordConfirm.value;
|
|
// const name = form.userName.value.trim();
|
|
// const email = form.userEmail.value.trim();
|
|
// const phone = form.userPhone.value.trim();
|
|
|
|
// if (!isIdChecked || checkedUserId !== form.userId.value.trim()) {
|
|
// alert('아이디 중복확인을 해주세요.');
|
|
// return;
|
|
// }
|
|
|
|
// if (!id || !pw || !pw2 || !name || !email || !phone) {
|
|
// alert('필수 항목을 모두 입력하세요.');
|
|
// return;
|
|
// }
|
|
|
|
// if (!REGEX.password.test(pw)) {
|
|
// alert('비밀번호 규칙을 확인하세요.');
|
|
// return;
|
|
// }
|
|
|
|
// if (pw !== pw2) {
|
|
// alert('비밀번호가 일치하지 않습니다.');
|
|
// return;
|
|
// }
|
|
|
|
// if (!REGEX.name.test(name)) {
|
|
// alert('이름에 특수문자는 사용할 수 없습니다.');
|
|
// return;
|
|
// }
|
|
|
|
// if (!REGEX.phone.test(phone)) {
|
|
// alert('휴대전화번호 형식이 올바르지 않습니다.');
|
|
// return;
|
|
// }
|
|
|
|
// // 여기까지 왔으면 → 서버 signup 요청
|
|
// submitSignup();
|
|
// });
|
|
// }
|