diff --git a/items.html b/items.html new file mode 100644 index 00000000..68d8f88f --- /dev/null +++ b/items.html @@ -0,0 +1,11 @@ + + + + + + items + + +

item pages

+ + diff --git a/js/ValidationRules.js b/js/ValidationRules.js new file mode 100644 index 00000000..2a37e068 --- /dev/null +++ b/js/ValidationRules.js @@ -0,0 +1,40 @@ +function isValidEmail(email) { + const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + return regex.test(email) +} + +export const validationRules = { + email: [ + { condition: (v) => !v, message: '이메일을 입력해주세요.' }, + { + condition: (v) => !isValidEmail(v), + message: '잘못된 이메일 형식입니다.', + }, + ], + password: [ + { condition: (v) => !v, message: '비밀번호를 입력해주세요.' }, + { + condition: (v) => v.length < 8, + message: '비밀번호를 8자 이상 입력해주세요.', + }, + ], + nickname: [{ condition: (v) => !v, message: '닉네임을 입력해주세요.' }], +} + +export function validateInput( + input, + type, + validateErrorMessage, + showError, + clearError +) { + const value = input.value.trim() + const errorEl = validateErrorMessage(input) + const failed = validationRules[type].find(({ condition }) => condition(value)) + + if (failed) { + showError(input, errorEl, failed.message) + } else { + clearError(input, errorEl) + } +} diff --git a/js/login.js b/js/login.js new file mode 100644 index 00000000..55458eae --- /dev/null +++ b/js/login.js @@ -0,0 +1,95 @@ +import { validateInput } from './ValidationRules.js' + +document.addEventListener('DOMContentLoaded', function () { + const emailInput = document.getElementById('email') + const passwordInput = document.getElementById('password') + const loginButton = document.querySelector('.login_button') + + // 이메일 부분 + + emailInput.addEventListener('blur', () => { + validateInput( + emailInput, + 'email', + validateErrorMessage, + showError, + clearError + ) + updateButtonState() + }) + + // 비밀번호 부분 + + passwordInput.addEventListener('blur', () => { + validateInput( + passwordInput, + 'password', + validateErrorMessage, + showError, + clearError + ) + updateButtonState() + }) + + function showError(input, errorElement, message) { + const wrapper = input.closest('.login_password_wrap') || input + wrapper.classList.add('error') + errorElement.textContent = message + errorElement.style.display = 'block' + } + + function clearError(input, errorElement) { + const wrapper = input.closest('.login_password_wrap') || input + wrapper.classList.remove('error') + errorElement.textContent = '' + errorElement.style.display = 'none' + } + + function validateErrorMessage(input) { + let wrapper = input.closest('.login_password_wrap') || input + let next = wrapper.nextElementSibling + if (!next || !next.classList.contains('error-message')) { + const error = document.createElement('p') + error.className = 'error-message' + error.style.color = 'red' + error.style.fontSize = '14px' + error.style.marginTop = '4px' + wrapper.parentNode.insertBefore(error, wrapper.nextSibling) + return error + } + return next + } + + function updateButtonState() { + const emailValue = emailInput.value.trim() + const passwordValue = passwordInput.value.trim() + + const hasEmailError = validateErrorMessage(emailInput).textContent !== '' + const hasPasswordError = + validateErrorMessage(passwordInput).textContent !== '' + + const isValid = + emailValue && passwordValue && !hasEmailError && !hasPasswordError + + loginButton.disabled = !isValid + + if (isValid) { + loginButton.classList.add('active') + } else { + loginButton.classList.remove('active') + } + } + + emailInput.addEventListener('input', updateButtonState) + passwordInput.addEventListener('input', updateButtonState) + + const loginForm = document.querySelector('.login_form_container') + + loginForm.addEventListener('submit', function (e) { + e.preventDefault() // 폼 제출 방지 + if (!loginButton.disabled) { + window.location.href = '/items.html' + } + }) + updateButtonState() +}) diff --git a/js/signup.js b/js/signup.js new file mode 100644 index 00000000..cfc9dcfd --- /dev/null +++ b/js/signup.js @@ -0,0 +1,142 @@ +import { validateInput } from './ValidationRules.js' + +document.addEventListener('DOMContentLoaded', function () { + const emailInput = document.getElementById('email') + const nicknameInput = document.getElementById('nickname') + const passwordInput = document.getElementById('password') + const passwordCheckInput = document.getElementById('passwordCheck') + const signupButton = document.querySelector('.login_button') + const signupForm = document.querySelector('.signup_form_frame') + + // 이메일 부분 + emailInput.addEventListener('blur', () => { + validateInput( + emailInput, + 'email', + validateErrorMessage, + showError, + clearError + ) + updateButtonState() + }) + + // 닉네임 부분 + nicknameInput.addEventListener('blur', () => + validateInput( + nicknameInput, + 'nickname', + validateErrorMessage, + showError, + clearError + ) + ) + + // 비밀번호 부분 + passwordInput.addEventListener('blur', () => + validateInput( + passwordInput, + 'password', + validateErrorMessage, + showError, + clearError + ) + ) + + // 비밀번호 확인 부분 + passwordCheckInput.addEventListener('blur', () => { + const pwValue = passwordInput.value.trim() + const checkValue = passwordCheckInput.value.trim() + const errorMsg = validateErrorMessage(passwordCheckInput) + + if (pwValue !== checkValue) { + showError(passwordCheckInput, errorMsg, '비밀번호가 일치하지 않습니다.') + } else { + clearError(passwordCheckInput, errorMsg) + } + + updateButtonState() + }) + + emailInput.addEventListener('input', updateButtonState) + nicknameInput.addEventListener('input', updateButtonState) + passwordInput.addEventListener('input', updateButtonState) + passwordCheckInput.addEventListener('input', updateButtonState) + + function updateButtonState() { + const emailValue = emailInput.value.trim() + const nicknameValue = nicknameInput.value.trim() + const passwordValue = passwordInput.value.trim() + const passwordCheckValue = passwordCheckInput.value.trim() + + const hasEmailError = validateErrorMessage(emailInput).textContent !== '' + const hasNicknameError = + validateErrorMessage(nicknameInput).textContent !== '' + const hasPasswordError = + validateErrorMessage(passwordInput).textContent !== '' + const hasPasswordCheckError = + validateErrorMessage(passwordCheckInput).textContent !== '' + + const isValid = + emailValue && + nicknameValue && + passwordValue && + passwordCheckValue && + !hasEmailError && + !hasNicknameError && + !hasPasswordError && + !hasPasswordCheckError + + signupButton.disabled = !isValid + + if (isValid) { + signupButton.classList.add('active') + } else { + signupButton.classList.remove('active') + } + } + + // 회원가입시 로그인페이지로 + signupForm.addEventListener('submit', function (e) { + e.preventDefault() + if (!signupButton.disabled) { + window.location.href = '/login/index.html' + } + }) + + function isValidEmail(email) { + const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + return regex.test(email) + } + + function showError(input, errorElement, message) { + const wrapper = input.closest('.login_password_wrap') || input + wrapper.classList.add('error') + errorElement.textContent = message + errorElement.style.display = 'block' + } + + function clearError(input, errorElement) { + const wrapper = input.closest('.login_password_wrap') || input + wrapper.classList.remove('error') + errorElement.textContent = '' + errorElement.style.display = 'none' + } + + function validateErrorMessage(input) { + let wrapper = input.closest('.login_password_wrap') || input + let next = wrapper.nextElementSibling + if (!next || !next.classList.contains('error-message')) { + const error = document.createElement('p') + error.className = 'error-message' + error.style.color = 'red' + error.style.fontSize = '14px' + error.style.marginTop = '4px' + wrapper.parentNode.insertBefore(error, wrapper.nextSibling) + return error + } + return next + } + + // 페이지 로드 초기화 + updateButtonState() +}) diff --git a/login/index.html b/login/index.html index 81b40fd1..2293ba83 100644 --- a/login/index.html +++ b/login/index.html @@ -79,5 +79,6 @@ + diff --git a/login/login.css b/login/login.css index 3585a546..e34e9df9 100644 --- a/login/login.css +++ b/login/login.css @@ -262,3 +262,28 @@ html { max-width: 640px; } } + +.error { + border: 1px solid red; +} + +.error-message { + color: red; + font-size: 14px; + margin-top: 4px; +} + +.login_input.error { + border: 1px solid red !important; +} + +.login_password_wrap.error { + border: 1px solid red; +} + +.login_button:disabled { + background-color: #d1d5db; + color: white; + cursor: not-allowed; + opacity: 1; +} diff --git a/login/signup.html b/login/signup.html index b341ce42..f9b67125 100644 --- a/login/signup.html +++ b/login/signup.html @@ -96,5 +96,6 @@ +