-
Notifications
You must be signed in to change notification settings - Fork 24
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
[함헌규] sprint3 #34
The head ref may contain hidden characters: "basic-\uD568\uD5CC\uADDC-sprint3"
[함헌규] sprint3 #34
Changes from all commits
89e4d71
c52b985
a61f3a1
b1f04dc
5abc028
bec555f
9d963cf
317a2e4
b2c9c00
9cc4d47
2a56f37
82e4dc5
e3b39c2
1143857
af9afbc
3f145ba
3a4284f
f6f2b77
fab2a2b
f22ed98
c3713df
05d4e18
d567ce8
3f1f036
8d67925
6a41751
2bfc1e0
4230149
b50523c
5342893
c639bf5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { VALIDATION_VALUES } from "./validationValues.js"; | ||
|
||
export const ERROR_MESSAGES = { | ||
inputEmail: "이메일을 입력해주세요.", | ||
invalidEmail: "잘못된 이메일 형식입니다", | ||
inputPassword: "비밀번호를 입력해주세요.", | ||
inputValidLengthPassword: `비밀번호를 ${VALIDATION_VALUES.passwordLength}자 이상 입력해주세요.`, | ||
passwordNotMatch: "비밀번호가 일치하지 않습니다.", | ||
emailAlreadyInUse: "사용 중인 이메일입니다", | ||
inputNickname: "닉네임을 입력해주세요.", | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export const KEYS = { | ||
email: "email", | ||
nickname: "nickname", | ||
password: "password", | ||
confirmPassword: "confirmPassword", | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export const USER_DATA = [ | ||
{ email: "codeit1@codeit.com", password: "codeit101!" }, | ||
{ email: "codeit2@codeit.com", password: "codeit202!" }, | ||
{ email: "codeit3@codeit.com", password: "codeit303!" }, | ||
{ email: "codeit4@codeit.com", password: "codeit404!" }, | ||
{ email: "codeit5@codeit.com", password: "codeit505!" }, | ||
{ email: "codeit6@codeit.com", password: "codeit606!" }, | ||
]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const VALIDATION_VALUES = { | ||
passwordLength: 8, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import $ from "../utils/query.js"; | ||
|
||
class Sign { | ||
constructor() { | ||
// 인풋 값의 유효성 상태를 저장하는 객체 | ||
this.inputValidState = {}; | ||
// 페이지의 인풋 DOM요소 | ||
this.inputs = {}; | ||
// 인풋 값의 유효성검사 메소드 | ||
this.validateMethods = {}; | ||
} | ||
|
||
init() { | ||
this.handleInputFocusout(); | ||
this.setFormSubmit(); | ||
this.setCloseButton(); | ||
this.handleToggleButton(); | ||
} | ||
|
||
setState(newState) { | ||
this.inputValidState = { | ||
...this.inputValidState, | ||
...newState, | ||
}; | ||
$("#submit-button").disabled = Object.values(this.inputValidState).some((state) => !state); | ||
} | ||
|
||
toggleInputError(e, message = "") { | ||
const errorMessageNode = e.target.closest("section").querySelector(".message"); | ||
errorMessageNode.innerText = message; | ||
if (message.length) { | ||
e.target.classList.add("error"); | ||
errorMessageNode.setAttribute("aria-hidden", false); | ||
return errorMessageNode.classList.add("show"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 특정 요소에 display:none으로 설정 후 show클래스에 display:block을 설정해서 요소를 표시할 때 show 클래스를 추가하는 식으로 구현했는데 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 방식은 여러가지가 있을수 있겠으나 에러메세지가 있거나, 없거나를 생각한다면 innerText를 빈문자열로, 혹은 에러메세지로 설정해서 표시해주시는게 좋을것 같아요! 현재는 error를 보여주는 텍스트의 레이아웃(크기)이 잡혀있기에 이런식으로 처리해도 무방할 것 같습니다 |
||
} | ||
e.target.classList.remove("error"); | ||
errorMessageNode.setAttribute("aria-hidden", true); | ||
errorMessageNode.classList.remove("show"); | ||
} | ||
|
||
handleInputFocusout() { | ||
for (const key in this.inputs) { | ||
this.inputs[key].addEventListener("focusout", (e) => { | ||
const { value } = e.target; | ||
const message = this.validateMethods[key](value); | ||
this.toggleInputError(e, message); | ||
this.setState({ [key]: message.length === 0 }); | ||
}); | ||
} | ||
} | ||
|
||
setFormSubmit() { | ||
$("form").addEventListener("submit", (e) => { | ||
e.preventDefault(); | ||
this.onSubmit(); | ||
}); | ||
} | ||
|
||
showModal(message) { | ||
$("#modal-container").classList.add("show"); | ||
$("#error-message").innerText = message; | ||
} | ||
|
||
setCloseButton() { | ||
$("#modal-close-button").addEventListener("click", () => { | ||
$("#modal-container").classList.remove("show"); | ||
}); | ||
} | ||
|
||
getValues() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아래 리뷰하다가 다시 돌아왔는데, 입력필드의 어떠한 값을 가져올때 항상 전체를 가져와서 하나를 사용하는식으로 사용될것 같아요. |
||
return Object.values(this.inputs).reduce((acc, input, index) => { | ||
return { ...acc, [Object.keys(this.inputs)[index]]: input.value }; | ||
}, {}); | ||
} | ||
|
||
onSubmit() {} | ||
|
||
handleSubmitSuccess() { | ||
window.location.href = "../items/index.html"; | ||
} | ||
|
||
handleSubmitFailure(message) { | ||
this.showModal(message); | ||
} | ||
|
||
togglePasswordVisibility(e) { | ||
const { target } = e; | ||
target.classList.toggle("fa-eye-slash"); | ||
target.classList.toggle("fa-eye"); | ||
const input = target.closest("div").querySelector("input"); | ||
input.type === "text" ? (input.type = "password") : (input.type = "text"); | ||
} | ||
|
||
handleToggleButton() { | ||
document | ||
.querySelectorAll(".eye-icon") | ||
.forEach((icon) => icon.addEventListener("click", this.togglePasswordVisibility)); | ||
} | ||
} | ||
|
||
export default Sign; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import $ from "./utils/query.js"; | ||
import { USER_DATA } from "./constants/userData.js"; | ||
import { ERROR_MESSAGES } from "./constants/messages.js"; | ||
import Sign from "./core/sign.js"; | ||
import { validator } from "./utils/validator.js"; | ||
import { KEYS } from "./constants/names.js"; | ||
|
||
class LoginForm extends Sign { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상속을 이용해서 처리해주신 부분 굉장히 좋은것 같습니다! |
||
constructor() { | ||
super(); | ||
this.inputValidState = { | ||
[KEYS.email]: false, | ||
[KEYS.password]: false, | ||
}; | ||
this.inputs = { | ||
[KEYS.email]: $("#email"), | ||
[KEYS.password]: $("#password"), | ||
}; | ||
this.validateMethods = { | ||
[KEYS.email]: validator.validateEmail, | ||
[KEYS.password]: validator.validatePassword, | ||
}; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 입력창 DOM 요소와 입력창의 값에 대한 유효성 검사 함수를 이렇게 배열형태로 필드로 저장하고 사용하는 방식은 적절한 방식인지 궁금합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 작성해주신대로 어떠한 비즈니스로직을 구성할 때 미리 필요한 항목들을 배열형태로 작성하는 방식은 많이 사용하는 방식입니다! 그리고 KEYS.email, KEYS.password처럼 명시적인 이름을 붙혀주셧기에 확인하기도 쉬울 것 같아요. 하지만 이러한 경우의수가 굉장히 많을때는 조금 경계해야 할 필요도 있습니다. 성능상의 문제가 발생하거나, 잘 작성된 주석이 없다면 다른사람이 코드를 읽기 불편한 상황이 생길수 있습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 동일한 key를 가진 객체형태로 변경하고 key를 통해 참조하도록 변경했습니다! |
||
|
||
onSubmit() { | ||
const values = this.getValues(); | ||
const matchingAccount = USER_DATA.find((data) => data.email === values.email); | ||
matchingAccount?.password === values.password | ||
? this.handleLoginSuccess() | ||
: this.handleLoginFailure(ERROR_MESSAGES.passwordNotMatch); | ||
} | ||
|
||
handleLoginSuccess() { | ||
super.handleSubmitSuccess(); | ||
// 이후 추가 로직 작성 | ||
} | ||
handleLoginFailure(message) { | ||
super.handleSubmitFailure(message); | ||
// 이후 추가 로직 작성 | ||
} | ||
} | ||
|
||
new LoginForm().init(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import $ from "./utils/query.js"; | ||
import { ERROR_MESSAGES } from "./constants/messages.js"; | ||
import { USER_DATA } from "./constants/userData.js"; | ||
import Sign from "./core/sign.js"; | ||
import { validator } from "./utils/validator.js"; | ||
import { KEYS } from "./constants/names.js"; | ||
|
||
class signupForm extends Sign { | ||
constructor() { | ||
super(); | ||
this.inputValidState = { | ||
[KEYS.email]: false, | ||
[KEYS.nickname]: false, | ||
[KEYS.password]: false, | ||
[KEYS.confirmPassword]: false, | ||
}; | ||
this.inputs = { | ||
[KEYS.email]: $("#email"), | ||
[KEYS.nickname]: $("#nickname"), | ||
[KEYS.password]: $("#password"), | ||
[KEYS.confirmPassword]: $("#confirm-password"), | ||
}; | ||
this.validateMethods = { | ||
[KEYS.email]: validator.validateEmail, | ||
[KEYS.nickname]: validator.validateNickname, | ||
[KEYS.password]: validator.validatePassword, | ||
[KEYS.confirmPassword]: validator.validatePassword, | ||
}; | ||
} | ||
|
||
onSubmit() { | ||
const values = this.getValues(); | ||
const emailAlreadyInUse = USER_DATA.find((data) => data.email === values.email); | ||
const passwordMatch = values.password === values.confirmPassword; | ||
emailAlreadyInUse | ||
? this.handleSignupFailure(ERROR_MESSAGES.emailAlreadyInUse) | ||
: !passwordMatch | ||
? this.handleSignupFailure(ERROR_MESSAGES.passwordNotMatch) | ||
: this.handleSignupSuccess(); | ||
} | ||
|
||
handleSignupSuccess() { | ||
super.handleSubmitSuccess(); | ||
// 이후 추가 로직 작성 | ||
} | ||
handleSignupFailure(message) { | ||
super.handleSubmitFailure(message); | ||
// 이후 추가 로직 작성 | ||
} | ||
} | ||
|
||
new signupForm().init(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const $ = (query) => document.querySelector(query); | ||
|
||
export default $; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { VALIDATION_VALUES } from "../constants/validationValues.js"; | ||
import { ERROR_MESSAGES } from "../constants/messages.js"; | ||
|
||
const emailRegex = /^[a-z0-9]+@[a-z]+\.[a-z]{2,}(\.[a-z]{2,})?$/; | ||
|
||
export const validator = { | ||
validateEmail(email) { | ||
if (!email.length) return ERROR_MESSAGES.inputEmail; | ||
if (!emailRegex.test(email)) return ERROR_MESSAGES.invalidEmail; | ||
return ""; | ||
}, | ||
validatePassword(password) { | ||
if (!password.length) return ERROR_MESSAGES.inputPassword; | ||
if (password.length < VALIDATION_VALUES.passwordLength) | ||
return ERROR_MESSAGES.inputValidLengthPassword; | ||
return ""; | ||
}, | ||
validateNickname(nickname) { | ||
if (!nickname.length) return ERROR_MESSAGES.inputNickname; | ||
return ""; | ||
}, | ||
|
||
validatePasswordConfirm(password, confirmPassword) { | ||
if (password !== confirmPassword) return ERROR_MESSAGES.passwordNotMatch; | ||
return ""; | ||
}, | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 파일전체적으로, 정규식을 통해서 값을 검증하는것, 얼리리턴 사용해주신것, 에러의 메세지를 상수값으로 미리 선언해두신것 모두 좋은것 같습니다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
생성자에서 만들어주신 class 내부 각 필드들이 어떠한 역활을 하는지 주석으로 적어주시면 좋을것 같아요