Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[나윤주] sprint4 #139

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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.DS_Store
.DS_Store
assets/.DS_Store
6 changes: 3 additions & 3 deletions assets/css/style.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

138 changes: 138 additions & 0 deletions assets/js/auth/form-validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
export const form = document.querySelector('.form');
export const inputList = form.querySelectorAll("input");
export const submitBtn = document.querySelector('#submitBtn');
export const VALIDATE_LIST = Object.freeze({
EMAIL: 'val-email',
NICKNAME: 'val-nickname',
PASSWORD: 'val-password',
CONFIRM_PASSWORD: 'val-confirm-password',
})
// 유효값에 대한 정의
export const validate = {
errorPlacement: function (e, message) {
const inputFormDiv = e.parentNode;
let errorDiv = inputFormDiv.querySelector('.error-message');
Copy link
Collaborator

Choose a reason for hiding this comment

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

p4;
요부분은 OR 연산자를 통해서도 조금 더 축약할 수 있을 것 같아요!

const errorDiv = inputFormDiv.querySelector('.error-message') || document.createElement('div');
// OR(||) 연산자는 첫번째 값이 falsy한 경우 두번째 값을 반환합니다.
// 따라서 inputFormDiv.querySelector('.error-message');가 null인경우 자동으로 document.createElement('div'); 를 할당하게 됩니다.

errorDiv.classList.add('error-message');
// classList.add는 클래스명이 없다면 추가하고, 이미 있다면 아무 동작도 하지 않습니다.

따라서 위와 같이 쓰면 아예 if문을 없애볼 수도 있을 것 같아요!

if (!errorDiv) {
errorDiv = document.createElement('div');
errorDiv.classList.add('error-message');
}
errorDiv.innerHTML = message;
inputFormDiv.appendChild(errorDiv);

},
showError: function (e, message) {
const inputFormDiv = e.parentNode;
inputFormDiv.classList.remove('valid');
e.classList.add('error-border');
e.dataset.valid = 'false';
this.errorPlacement(e, message);
},
success: function (e) {
const inputFormDiv = e.parentNode;
let errorDiv = inputFormDiv.querySelector('.error-message');
Copy link
Collaborator

Choose a reason for hiding this comment

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

p4;
요 errorDiv도 재할당되지 않으니, const로 선언해도 될 것 같아요!

e.classList.remove('error-border');
if (errorDiv) {
errorDiv.remove();
}
inputFormDiv.classList.add('valid');
e.dataset.valid = 'true';
},
messages: {
[VALIDATE_LIST.EMAIL]: {
required: '이메일을 입력해주세요.',
pattern: '잘못된 이메일형식입니다.',
},
[VALIDATE_LIST.NICKNAME]: '닉네임을 입력해주세요.',
[VALIDATE_LIST.PASSWORD]: {
required: '비밀번호를 입력해주세요.',
minlength: '비밀번호를 8자 이상 입력해주세요.',
},
[VALIDATE_LIST.CONFIRM_PASSWORD]: {
required: '비밀번호를 입력해주세요.',
minlength: '비밀번호를 8자 이상 입력해주세요.',
equalTo: '비밀번호가 일치하지 않습니다.',
}
},
rules: {
[VALIDATE_LIST.EMAIL]: {
required: true,
pattern: /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/,
},
[VALIDATE_LIST.NICKNAME]: {
required: true,
},
[VALIDATE_LIST.PASSWORD]: {
required: true,
minlength: 8,
},
[VALIDATE_LIST.CONFIRM_PASSWORD]: {
required: true,
minlength: 8,
equalTo: '#password',
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

상수화 시키는 부분을 적용해주셨네요!
이렇게 반복적으로 자주 사용되는 객체의 key나 변수 등을 상수로 관리하는 습관을 들이면
코드 베이스가 거대해지는 상황에서 휴먼에러를 많이 방지할 수 있을 것 같아요!👍

}

// input 유효값 check
export function checkInputs(input) {
const inputType = input.name;
const inputValName = `val-${inputType}`;
const value = input.value.trim();
const rules = validate.rules[inputValName];
const message = validate.messages[inputValName];

// Specific validation checks
if (inputType === 'email') {
if (rules.required && !value) {
validate.showError(input, message.required);
return false;
}
if (value && !rules.pattern.test(value)) {
validate.showError(input, message.pattern);
return false;
}
validate.success(input);
return true;
} else if (inputType === 'nickname') {
if (rules && !value) {
validate.showError(input, message);
return false;
}
validate.success(input);
return true;
} else if (inputType === 'password') {
if (rules.required && !value) {
validate.showError(input, message.required);
return false;
}
if (value && value.length < rules.minlength) {
validate.showError(input, message.minlength);
return false;
}
validate.success(input);

} else if (inputType === 'confirm-password') {
if (rules.required && !value) {
validate.showError(input, message.required);
return false;
}
if (value && value.length < rules.minlength) {
validate.showError(input, message.minlength);
return false;
}
if (value && value !== document.querySelector('#password').value) {
validate.showError(input, message.equalTo);
return false;
}
validate.success(input);
return true;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

p4;
지난번 리뷰에도 남겨드렸는데, 요 부분은 나중에 시간이 될 때 천천히 조금 더 보기 좋게 조건문을 개선해보는 것도 좋을 것 같아요!


// form 전체에 대한 검증
export function checkAllInput() {
let formSubmitDone = [...form.querySelectorAll('input')].every(input => input.dataset.valid === 'true');
Copy link
Collaborator

Choose a reason for hiding this comment

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

앞으로 거의 모든 변수에는 기본적으로 const만 사용하는 연습을 해봐요!
그러다가 정말 let이 필요할 때 그때만 let을 사용하는 습관을 들이면 좋을 것 같아요!

submitBtn.disabled = !formSubmitDone;
return formSubmitDone;
}

51 changes: 51 additions & 0 deletions assets/js/auth/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
form,
inputList,
checkInputs,
checkAllInput,
} from './form-validation.js';

inputList.forEach((input) => {
input.addEventListener('blur', function () {
this.parentNode.classList.add('is-error');
checkInputs(input);
});
input.addEventListener('keyup', () => {
checkInputs(input);
checkAllInput();
})
});

// form 제출
form.addEventListener('submit', function (event) {
event.preventDefault();
if (checkAllInput) {
alert('로그인성공');
window.location.href = '/items.html';
}
});

// 패스워드 보기
function passwordToggle(e) {
let button = e.currentTarget;
let passwordInput = button.parentElement.querySelector('input');
let toggleIcon = document.createElement('i');
toggleIcon.classList.add('icon');

const shouldShowPassword = passwordInput.type === 'password';
passwordInput.type = shouldShowPassword ? 'text' : 'password';

toggleIcon.classList.toggle('ic_visible_on', !shouldShowPassword);
toggleIcon.classList.toggle('ic_visible_off', shouldShowPassword);

const ariaLabel = shouldShowPassword ? '비밀번호 숨기기' : '비밀번호 보기';
this.setAttribute("aria-label", ariaLabel);

button.innerHTML = '';
button.appendChild(toggleIcon);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

굳! 삼항연산자와 변수를 통해 훨씬 이 부분의 코드의 가독성이 좋아진 것 같아요!


const passwordToggleBtns = document.querySelectorAll('.password-toggle-button');
passwordToggleBtns.forEach(btn => {
btn.addEventListener('click', passwordToggle);
});
52 changes: 52 additions & 0 deletions assets/js/auth/signup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
form,
inputList,
checkInputs,
checkAllInput,
} from './form-validation.js';

inputList.forEach((input) => {
input.addEventListener('blur', function () {
this.parentNode.classList.add('is-error');
checkInputs(input);
});
input.addEventListener('keyup', () => {
checkInputs(input);
checkAllInput();
})
});

// form 제출
form.addEventListener('submit', function (event) {
event.preventDefault();
if (checkAllInput) {
alert('회원가입성공');
window.location.href = '/signup.html';
}
});


// 패스워드 보기
function passwordToggle(e) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

login과 signup에 반복되어 사용되는 요런 함수들은, 천천히 시간 날때마다 공통 함수로 분리하는 연습을 해보면 좋을 것 같아요!

let button = e.currentTarget;
let passwordInput = button.parentElement.querySelector('input');
let toggleIcon = document.createElement('i');
toggleIcon.classList.add('icon');

const shouldShowPassword = passwordInput.type === 'password';
passwordInput.type = shouldShowPassword ? 'text' : 'password';

toggleIcon.classList.toggle('ic_visible_on', !shouldShowPassword);
toggleIcon.classList.toggle('ic_visible_off', shouldShowPassword);

const ariaLabel = shouldShowPassword ? '비밀번호 숨기기' : '비밀번호 보기';
this.setAttribute("aria-label", ariaLabel);

button.innerHTML = '';
button.appendChild(toggleIcon);
}

const passwordToggleBtns = document.querySelectorAll('.password-toggle-button');
passwordToggleBtns.forEach(btn => {
btn.addEventListener('click', passwordToggle);
});
27 changes: 1 addition & 26 deletions assets/js/signup2.js → assets/js/auth/signup2.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ const form = document.querySelector("form");
const inputList = form.querySelectorAll("input");
const submitBtn = form.querySelector("#submitBtn");

submitBtn.disabled = true;

inputList.forEach((input) => {
input.addEventListener("keyup", function () {
checkInputs(input);
Expand Down Expand Up @@ -98,31 +96,8 @@ form.addEventListener("submit", (e) => {
}
});



// 패스워드 토글기능
let passwordToggleBtns = document.querySelectorAll('.password-toggle-button');

function passwordToggle(e) {
let button = e.currentTarget;
let passwordInput = button.parentElement.querySelector('input');
let toggleIcon = document.createElement('i');
toggleIcon.classList.add('icon');
if (passwordInput.type == "password") {
passwordInput.type = "text";
toggleIcon.classList.remove('ic_visible_on');
toggleIcon.classList.add('ic_visible_off')
this.setAttribute("aria-label", "비밀번호 숨기기");
} else {
passwordInput.type = "password";
toggleIcon.classList.remove('ic_visible_off');
toggleIcon.classList.add('ic_visible_on');
this.setAttribute("aria-label", "비밀번호 보기");
}
button.innerHTML = '';
button.appendChild(toggleIcon);
}

const passwordToggleBtns = document.querySelectorAll('.password-toggle-button');
passwordToggleBtns.forEach(btn => {
btn.addEventListener('click', passwordToggle);
});
Loading
Loading