/* ========================= 전역 상태값 ========================= */ 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(); // }); // }