Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<img src="/images/logo/panda-market-logo.png" class="logo-img" />
판다마켓
</a>
<a href="/html/login.html" class="btn btn-sm-48">로그인</a>
<a href="/html/signin.html" class="btn btn-sm-48">로그인</a>
</div>
</header>
<main>
Expand Down
25 changes: 15 additions & 10 deletions html/login.html → html/signin.html
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네이밍도 좀더 좋은것같네요ㅎㅎ

Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
<label for="email">이메일</label>
</div>
<input type="email" id="email" placeholder="이메일을 입력하세요" />
<span id="emailEmptyError" class="error-message">
이메일을 입력해주세요.
</span>
<span id="emailInvalidError" class="error-message">
잘못된 이메일 형식입니다.
</span>
Comment on lines +29 to +34
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 각각의 에러 상황을 표시해주는것도 좋지만 하나만 만들어두고 innterText를 바꾸는 식으로 접근하는건 어떨까요?

왜냐하면 이렇게 되어있으면 실수로 동시에 2개의 에러 메시지가 나올 가능성도 있기도 하고, DOM이 조금 지저분해질 수 도 있어서요ㅠ

물론 지금은 규모가 작기도 해서 괜찮지만요ㅎㅎ

</form>
<form>
<div class="label">
Expand All @@ -35,17 +41,16 @@
<input
type="password"
id="password"
placeholder="비밀번호를 입력하세요"
/>
<img
src="/images/login/pw-eye-btn-on.png"
class="pw-eye-btn-on done"
/>
<img
src="/images/login/pw-eye-btn-off.png"
class="pw-eye-btn-off"
placeholder="비밀번호를 입력해주세요"
/>
<img src="/images/login/pw-eye-btn-off.png" class="pw-eye-btn" />
</div>
<span id="passwordEmptyError" class="error-message">
비밀번호를 입력해주세요.
</span>
<span id="passwordLengthError" class="error-message">
비밀번호를 8자 이상 입력해주세요.
</span>
</form>
<a href="#" class="btn btn-lg auth-btn">로그인</a>
<div class="bottom-menu">
Expand All @@ -67,5 +72,5 @@
</div>
</body>

<script src="/js/login.js"></script>
<script src="/js/auth.js"></script>
</html>
44 changes: 24 additions & 20 deletions html/signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,21 @@
<label for="email">이메일</label>
</div>
<input type="email" id="email" placeholder="이메일을 입력해주세요" />
<span id="emailEmptyError" class="error-message">
이메일을 입력해주세요.
</span>
<span id="emailInvalidError" class="error-message">
잘못된 이메일 형식입니다.
</span>
</form>
<form>
<div class="label">
<label for="nickname">닉네임</label>
</div>
<input id="nickname" placeholder="닉네임을 입력해주세요" />
<span id="nicknameEmptyError" class="error-message">
닉네임을 입력해주세요.
</span>
</form>
<form>
<div class="label">
Expand All @@ -43,35 +52,30 @@
id="password"
placeholder="비밀번호를 입력해주세요"
/>
<img
src="/images/login/pw-eye-btn-on.png"
class="pw-eye-btn-on done"
/>
<img
src="/images/login/pw-eye-btn-off.png"
class="pw-eye-btn-off"
/>
<img src="/images/login/pw-eye-btn-off.png" class="pw-eye-btn" />
</div>
<span id="passwordEmptyError" class="error-message">
비밀번호를 입력해주세요.
</span>
<span id="passwordLengthError" class="error-message">
비밀번호를 8자 이상 입력해주세요.
</span>
</form>
<form>
<div class="label">
<label for="password-check">비밀번호 확인</label>
<label for="passwordCheck">비밀번호 확인</label>
</div>
<div class="password">
<input
type="password"
id="password-check"
id="passwordCheck"
placeholder="비밀번호를 다시 한 번 입력해주세요"
/>
<img
src="/images/login/pw-eye-btn-on.png"
class="pw-ck-eye-btn-on done"
/>
<img
src="/images/login/pw-eye-btn-off.png"
class="pw-ck-eye-btn-off"
/>
<img src="/images/login/pw-eye-btn-off.png" class="pw-ck-eye-btn" />
</div>
<span id="passwordCheckError" class="error-message">
비밀번호가 일치하지 않습니다.
</span>
</form>
<a href="#" class="btn btn-lg auth-btn">회원가입</a>
<div class="bottom-menu">
Expand All @@ -87,11 +91,11 @@
</div>
<div class="auth-guide">
이미 회원이신가요?
<a href="/html/login.html" class="auth-guide-btn">로그인</a>
<a href="/html/signin.html" class="auth-guide-btn">로그인</a>
</div>
</div>
</div>

<script src="/js/signup.js"></script>
<script src="/js/auth.js"></script>
</body>
</html>
175 changes: 175 additions & 0 deletions js/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// 각 필드의 유효성 검사 상태를 전역변수로 저정함
let isEmailValid = false;
let isNicknameValid = false;
let isPasswordValid = false;
let isPasswordCheckValid = false;

const emailInput = document.getElementById('email');
const nicknameInput = document.getElementById('nickname');
const passwordInput = document.getElementById('password');
const passwordCheckInput = document.getElementById('passwordCheck');

// 에러 표시 함수
function showError(input, errorId) {
const errorElement = document.getElementById(errorId);
errorElement.style.display = 'block';
input.style.border = '1px solid #f74747';
}

// 상태 초기화 함수(에러 메세지를 숨기고 입력 필드의 테두리를 원상태로 초기화)
function hideError(input, errorId) {
const errorElement = document.getElementById(errorId);
errorElement.style.display = 'none';
input.style.border = 'none';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

조금더 개선한다고 하면 이러한 부분들을 직접 스타일 조정하기보단 class로 처리해주시는게 좀더 좋긴 해요...!

inline style이 그다지 좋진 않거든요ㅠ

나중에 규모가 커지면 어디서 어떻게 바뀐건지 추적하기가 어려워져요ㅠ

}
Comment on lines +19 to +24
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와 이거 너무 잘하셨는데여ㅋㅋㅋ

공통적으로 반복되는 부분들을 이런식으로 뺴고 재사용을 많이 합니다...!


// 정규 표현식을 통한 이메일 유효성 검증
function emailValidation(email) {
const emailRegex = /^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
return emailRegex.test(email);
}

// 이메일 필드의 유효성 검사
function checkEmailValidity() {
const emailValue = emailInput.value;

// 에러 메세지 및 입력 필드의 상태를 먼저 초기화
isEmailValid = false;
hideError(emailInput, 'emailEmptyError');
hideError(emailInput, 'emailInvalidError');

if (!emailValue) {
showError(emailInput, 'emailEmptyError');
} else if (!emailValidation(emailValue)) {
showError(emailInput, 'emailInvalidError');
} else {
isEmailValid = true;
hideError(emailInput, 'emailEmptyError');
hideError(emailInput, 'emailInvalidError');
}

authBtnStatusChange();
}
// emailInput이 존재한다면 이벤트 발생 / 존재하지 않으면 발생시키지 않음
if (emailInput) {
emailInput.addEventListener('focusout', checkEmailValidity);
}

// 닉네임 필드의 유효성 검사
function checkNicknameValidity() {
const nicknameValue = nicknameInput.value;

isNicknameValid = false;
hideError(nicknameInput, 'nicknameEmptyError');

if (!nicknameValue) {
showError(nicknameInput, 'nicknameEmptyError');
} else {
isNicknameValid = true;
hideError(nicknameInput, 'nicknameEmptyError');
}

authBtnStatusChange();
}
if (nicknameInput) {
nicknameInput.addEventListener('focusout', checkNicknameValidity);
}

// 비밀번호 필드의 유효성 검사
function checkPasswordValidity() {
const passwordValue = passwordInput.value;

isPasswordValid = false;
hideError(passwordInput, 'passwordEmptyError');
hideError(passwordInput, 'passwordLengthError');

if (!passwordValue) {
showError(passwordInput, 'passwordEmptyError');
} else if (passwordValue.length < 8) {
showError(passwordInput, 'passwordLengthError');
} else {
isPasswordValid = true;
hideError(passwordInput, 'passwordEmptyError');
hideError(passwordInput, 'passwordLengthError');
}

authBtnStatusChange();
}
if (passwordInput) {
passwordInput.addEventListener('focusout', checkPasswordValidity);
}

// 비밀번호 확인 필드의 유효성 검사
function checkPasswordCheckValidity() {
const passwordValue = passwordInput.value;
const passwordCheckValue = passwordCheckInput.value;

isPasswordCheckValid = false;
hideError(passwordCheckInput, 'passwordCheckError');

if (passwordValue !== passwordCheckValue) {
showError(passwordCheckInput, 'passwordCheckError');
} else {
isPasswordCheckValid = true;
hideError(passwordCheckInput, 'passwordCheckError');
}

authBtnStatusChange();
}
if (passwordCheckInput) {
passwordCheckInput.addEventListener('focusout', checkPasswordCheckValidity);
}

// auth 버튼 비활성화/활성화 상태 변경
function authBtnStatusChange() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authBtnStatusChange 를 위쪽에서 사용하는데 authBtnStatusChange 함수는 아래에 정의가 되어있어요.

컴퓨터는 코드를 위에서부터 아래로 코드를 읽는데 authBtnStatusChange 가 정의되지 않은 상태에서도 authBtnStatusChange 함수를 찾아갔어요...!

이런 현상을 호이스팅 이라고 하는데, 한번 이번기회에 찾아보시면 좋을것같아요ㅎㅎ!

만약 function () 으로 함수를 생성하지 않고 const = () => {} 로 생성하셨으면 문제가 생겼을 수 있어요ㅠ

https://f-lab.kr/insight/understanding-javascript-hoisting?gad_source=1&gclid=CjwKCAiA3Na5BhAZEiwAzrfagJ1psdHlDMPqI8fbVhX535mvrKXKKUfd7u88RYF1sp-uVFzCioW6DxoC_ZQQAvD_BwE

const authBtn = document.querySelector('.auth-btn');

// 회원가입 페이지일때
if (nicknameInput && passwordCheckInput) {
if (
isEmailValid &&
isNicknameValid &&
isPasswordValid &&
isPasswordCheckValid
) {
authBtn.setAttribute('href', '/html/signin.html');
authBtn.style.backgroundColor = '#3692ff';
} else {
authBtn.setAttribute('href', '#');
authBtn.style.backgroundColor = '#9ca3af';
}
}
// 로그인 페이지일때
else {
if (isEmailValid && isPasswordValid) {
authBtn.setAttribute('href', '/html/items.html');
authBtn.style.backgroundColor = '#3692ff';
} else {
authBtn.setAttribute('href', '#');
authBtn.style.backgroundColor = '#9ca3af';
}
}
}

// 비밀번호 숨기기 버튼 구현
const pwEyeBtn = document.querySelector('.pw-eye-btn');
const pwCkEyeBtn = document.querySelector('.pw-ck-eye-btn');

function passwordEyeBtnChange(e) {
const pwInput = e.target.parentElement.querySelector('input');

if (e.target.getAttribute('src') === '/images/login/pw-eye-btn-off.png') {
e.target.setAttribute('src', '/images/login/pw-eye-btn-on.png');
pwInput.setAttribute('type', 'text');
} else {
e.target.setAttribute('src', '/images/login/pw-eye-btn-off.png');
pwInput.setAttribute('type', 'password');
}
Comment on lines +161 to +167
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

물론 src 에 있는 값을 통해 현재 상태를 구분해서 처리할 수 있어요ㅎㅎ!

틀린코드는 아닌데, 관리하기가 어려울것같아요.

ex) 이미지 아이콘이 변경된경우나 이미지 파일명이 변경된 경우에 까먹지 않고 auth.js 파일에 와서 변경된 부분을 같이 수정해주어야 하거든요.

만약

if (pwInput.type === "text") {
    e.target.setAttribute('src', '/images/login/pw-eye-btn-on.png');
    pwInput.setAttribute('type', 'text');
} else {
    e.target.setAttribute('src', '/images/login/pw-eye-btn-off.png');
    pwInput.setAttribute('type', 'password');
}

이렇게 해주면 굳이 이미지 경로를 알 필요까진 없을거에요ㅎㅎ!
(물론 지금도 잘 동작합니)

}

if (pwEyeBtn) {
pwEyeBtn.addEventListener('click', passwordEyeBtnChange);
}
if (pwCkEyeBtn) {
pwCkEyeBtn.addEventListener('click', passwordEyeBtnChange);
}
35 changes: 0 additions & 35 deletions js/login.js

This file was deleted.

Loading