Skip to content

Commit 4758e8d

Browse files
Merge pull request #163 from Sea0Soda/Basic-정해성-sprint4
[정해성] sprint4
2 parents 704288b + 53f3c76 commit 4758e8d

File tree

7 files changed

+315
-0
lines changed

7 files changed

+315
-0
lines changed

items.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>items</title>
7+
</head>
8+
<body>
9+
<h1>item pages</h1>
10+
</body>
11+
</html>

js/ValidationRules.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
function isValidEmail(email) {
2+
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
3+
return regex.test(email)
4+
}
5+
6+
export const validationRules = {
7+
email: [
8+
{ condition: (v) => !v, message: '이메일을 입력해주세요.' },
9+
{
10+
condition: (v) => !isValidEmail(v),
11+
message: '잘못된 이메일 형식입니다.',
12+
},
13+
],
14+
password: [
15+
{ condition: (v) => !v, message: '비밀번호를 입력해주세요.' },
16+
{
17+
condition: (v) => v.length < 8,
18+
message: '비밀번호를 8자 이상 입력해주세요.',
19+
},
20+
],
21+
nickname: [{ condition: (v) => !v, message: '닉네임을 입력해주세요.' }],
22+
}
23+
24+
export function validateInput(
25+
input,
26+
type,
27+
validateErrorMessage,
28+
showError,
29+
clearError
30+
) {
31+
const value = input.value.trim()
32+
const errorEl = validateErrorMessage(input)
33+
const failed = validationRules[type].find(({ condition }) => condition(value))
34+
35+
if (failed) {
36+
showError(input, errorEl, failed.message)
37+
} else {
38+
clearError(input, errorEl)
39+
}
40+
}

js/login.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { validateInput } from './ValidationRules.js'
2+
3+
document.addEventListener('DOMContentLoaded', function () {
4+
const emailInput = document.getElementById('email')
5+
const passwordInput = document.getElementById('password')
6+
const loginButton = document.querySelector('.login_button')
7+
8+
// 이메일 부분
9+
10+
emailInput.addEventListener('blur', () => {
11+
validateInput(
12+
emailInput,
13+
'email',
14+
validateErrorMessage,
15+
showError,
16+
clearError
17+
)
18+
updateButtonState()
19+
})
20+
21+
// 비밀번호 부분
22+
23+
passwordInput.addEventListener('blur', () => {
24+
validateInput(
25+
passwordInput,
26+
'password',
27+
validateErrorMessage,
28+
showError,
29+
clearError
30+
)
31+
updateButtonState()
32+
})
33+
34+
function showError(input, errorElement, message) {
35+
const wrapper = input.closest('.login_password_wrap') || input
36+
wrapper.classList.add('error')
37+
errorElement.textContent = message
38+
errorElement.style.display = 'block'
39+
}
40+
41+
function clearError(input, errorElement) {
42+
const wrapper = input.closest('.login_password_wrap') || input
43+
wrapper.classList.remove('error')
44+
errorElement.textContent = ''
45+
errorElement.style.display = 'none'
46+
}
47+
48+
function validateErrorMessage(input) {
49+
let wrapper = input.closest('.login_password_wrap') || input
50+
let next = wrapper.nextElementSibling
51+
if (!next || !next.classList.contains('error-message')) {
52+
const error = document.createElement('p')
53+
error.className = 'error-message'
54+
error.style.color = 'red'
55+
error.style.fontSize = '14px'
56+
error.style.marginTop = '4px'
57+
wrapper.parentNode.insertBefore(error, wrapper.nextSibling)
58+
return error
59+
}
60+
return next
61+
}
62+
63+
function updateButtonState() {
64+
const emailValue = emailInput.value.trim()
65+
const passwordValue = passwordInput.value.trim()
66+
67+
const hasEmailError = validateErrorMessage(emailInput).textContent !== ''
68+
const hasPasswordError =
69+
validateErrorMessage(passwordInput).textContent !== ''
70+
71+
const isValid =
72+
emailValue && passwordValue && !hasEmailError && !hasPasswordError
73+
74+
loginButton.disabled = !isValid
75+
76+
if (isValid) {
77+
loginButton.classList.add('active')
78+
} else {
79+
loginButton.classList.remove('active')
80+
}
81+
}
82+
83+
emailInput.addEventListener('input', updateButtonState)
84+
passwordInput.addEventListener('input', updateButtonState)
85+
86+
const loginForm = document.querySelector('.login_form_container')
87+
88+
loginForm.addEventListener('submit', function (e) {
89+
e.preventDefault() // 폼 제출 방지
90+
if (!loginButton.disabled) {
91+
window.location.href = '/items.html'
92+
}
93+
})
94+
updateButtonState()
95+
})

js/signup.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import { validateInput } from './ValidationRules.js'
2+
3+
document.addEventListener('DOMContentLoaded', function () {
4+
const emailInput = document.getElementById('email')
5+
const nicknameInput = document.getElementById('nickname')
6+
const passwordInput = document.getElementById('password')
7+
const passwordCheckInput = document.getElementById('passwordCheck')
8+
const signupButton = document.querySelector('.login_button')
9+
const signupForm = document.querySelector('.signup_form_frame')
10+
11+
// 이메일 부분
12+
emailInput.addEventListener('blur', () => {
13+
validateInput(
14+
emailInput,
15+
'email',
16+
validateErrorMessage,
17+
showError,
18+
clearError
19+
)
20+
updateButtonState()
21+
})
22+
23+
// 닉네임 부분
24+
nicknameInput.addEventListener('blur', () =>
25+
validateInput(
26+
nicknameInput,
27+
'nickname',
28+
validateErrorMessage,
29+
showError,
30+
clearError
31+
)
32+
)
33+
34+
// 비밀번호 부분
35+
passwordInput.addEventListener('blur', () =>
36+
validateInput(
37+
passwordInput,
38+
'password',
39+
validateErrorMessage,
40+
showError,
41+
clearError
42+
)
43+
)
44+
45+
// 비밀번호 확인 부분
46+
passwordCheckInput.addEventListener('blur', () => {
47+
const pwValue = passwordInput.value.trim()
48+
const checkValue = passwordCheckInput.value.trim()
49+
const errorMsg = validateErrorMessage(passwordCheckInput)
50+
51+
if (pwValue !== checkValue) {
52+
showError(passwordCheckInput, errorMsg, '비밀번호가 일치하지 않습니다.')
53+
} else {
54+
clearError(passwordCheckInput, errorMsg)
55+
}
56+
57+
updateButtonState()
58+
})
59+
60+
emailInput.addEventListener('input', updateButtonState)
61+
nicknameInput.addEventListener('input', updateButtonState)
62+
passwordInput.addEventListener('input', updateButtonState)
63+
passwordCheckInput.addEventListener('input', updateButtonState)
64+
65+
function updateButtonState() {
66+
const emailValue = emailInput.value.trim()
67+
const nicknameValue = nicknameInput.value.trim()
68+
const passwordValue = passwordInput.value.trim()
69+
const passwordCheckValue = passwordCheckInput.value.trim()
70+
71+
const hasEmailError = validateErrorMessage(emailInput).textContent !== ''
72+
const hasNicknameError =
73+
validateErrorMessage(nicknameInput).textContent !== ''
74+
const hasPasswordError =
75+
validateErrorMessage(passwordInput).textContent !== ''
76+
const hasPasswordCheckError =
77+
validateErrorMessage(passwordCheckInput).textContent !== ''
78+
79+
const isValid =
80+
emailValue &&
81+
nicknameValue &&
82+
passwordValue &&
83+
passwordCheckValue &&
84+
!hasEmailError &&
85+
!hasNicknameError &&
86+
!hasPasswordError &&
87+
!hasPasswordCheckError
88+
89+
signupButton.disabled = !isValid
90+
91+
if (isValid) {
92+
signupButton.classList.add('active')
93+
} else {
94+
signupButton.classList.remove('active')
95+
}
96+
}
97+
98+
// 회원가입시 로그인페이지로
99+
signupForm.addEventListener('submit', function (e) {
100+
e.preventDefault()
101+
if (!signupButton.disabled) {
102+
window.location.href = '/login/index.html'
103+
}
104+
})
105+
106+
function isValidEmail(email) {
107+
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
108+
return regex.test(email)
109+
}
110+
111+
function showError(input, errorElement, message) {
112+
const wrapper = input.closest('.login_password_wrap') || input
113+
wrapper.classList.add('error')
114+
errorElement.textContent = message
115+
errorElement.style.display = 'block'
116+
}
117+
118+
function clearError(input, errorElement) {
119+
const wrapper = input.closest('.login_password_wrap') || input
120+
wrapper.classList.remove('error')
121+
errorElement.textContent = ''
122+
errorElement.style.display = 'none'
123+
}
124+
125+
function validateErrorMessage(input) {
126+
let wrapper = input.closest('.login_password_wrap') || input
127+
let next = wrapper.nextElementSibling
128+
if (!next || !next.classList.contains('error-message')) {
129+
const error = document.createElement('p')
130+
error.className = 'error-message'
131+
error.style.color = 'red'
132+
error.style.fontSize = '14px'
133+
error.style.marginTop = '4px'
134+
wrapper.parentNode.insertBefore(error, wrapper.nextSibling)
135+
return error
136+
}
137+
return next
138+
}
139+
140+
// 페이지 로드 초기화
141+
updateButtonState()
142+
})

login/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,6 @@
7979
</div>
8080
</div>
8181
</div>
82+
<script type="module" src="../js/login.js"></script>
8283
</body>
8384
</html>

login/login.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,28 @@ html {
262262
max-width: 640px;
263263
}
264264
}
265+
266+
.error {
267+
border: 1px solid red;
268+
}
269+
270+
.error-message {
271+
color: red;
272+
font-size: 14px;
273+
margin-top: 4px;
274+
}
275+
276+
.login_input.error {
277+
border: 1px solid red !important;
278+
}
279+
280+
.login_password_wrap.error {
281+
border: 1px solid red;
282+
}
283+
284+
.login_button:disabled {
285+
background-color: #d1d5db;
286+
color: white;
287+
cursor: not-allowed;
288+
opacity: 1;
289+
}

login/signup.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,6 @@
9696
</div>
9797
</div>
9898
</div>
99+
<script type="module" src="../js/signup.js"></script>
99100
</body>
100101
</html>

0 commit comments

Comments
 (0)