-
Notifications
You must be signed in to change notification settings - Fork 39
[임재은] sprint4 #165
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
The head ref may contain hidden characters: "Basic-\uC784\uC7AC\uC740-sprint4"
[임재은] sprint4 #165
Changes from all commits
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,45 @@ | ||
| import { | ||
| validInput, | ||
| updateValidationUI, | ||
| togglePasswordVisibility, | ||
| checkButtonActivation, | ||
| } from "./utils.js"; | ||
|
|
||
| // 요소 선택 | ||
| const formElements = { | ||
| email: document.querySelector("#email"), | ||
| pw: document.querySelector("#pw"), | ||
| warnings: document.querySelectorAll(".warning-text"), | ||
| eyeIcon: document.querySelector(".eye-icon"), | ||
| loginBtn: document.querySelector(".form-btn"), | ||
| }; | ||
|
|
||
| // 공통 유효성 검사 핸들러 | ||
| const handleValidation = (type, inputEl, warningEl) => { | ||
| const result = validInput[type](inputEl); | ||
| updateValidationUI(inputEl, warningEl, result); | ||
| checkButtonActivation(formElements.loginBtn, "login"); | ||
| }; | ||
|
|
||
| // 이벤트 바인딩 | ||
| formElements.email.addEventListener("blur", () => { | ||
| handleValidation("email", formElements.email, formElements.warnings[0]); | ||
| }); | ||
|
|
||
| formElements.pw.addEventListener("input", () => { | ||
| handleValidation("pw", formElements.pw, formElements.warnings[1]); | ||
| }); | ||
|
|
||
| // 비밀번호 보기 토글 | ||
| formElements.eyeIcon.addEventListener("click", () => { | ||
| togglePasswordVisibility(formElements.eyeIcon, formElements.pw); | ||
| }); | ||
|
|
||
| // 로그인 버튼 클릭 | ||
| formElements.loginBtn.addEventListener("click", (e) => { | ||
| e.preventDefault(); | ||
| checkButtonActivation(formElements.loginBtn, "login"); | ||
| if (!formElements.loginBtn.disabled) { | ||
| window.location.href = "../page/items.html"; | ||
| } | ||
| }); | ||
|
Collaborator
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. 해당 파일에서도 위 login.js에서 드렸던 피드백 참고해보시고, 리팩토링 진행해볼까요? :) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| import { | ||
| validInput, | ||
| updateValidationUI, | ||
| togglePasswordVisibility, | ||
| checkButtonActivation, | ||
| } from "./utils.js"; | ||
|
|
||
| // 엘리먼트 모음 | ||
| const formElements = { | ||
| email: document.querySelector("#email"), | ||
| nickname: document.querySelector("#nickname"), | ||
| pw: document.querySelector("#pw"), | ||
| pwChk: document.querySelector("#pw-chk"), | ||
| }; | ||
| const warningText = document.querySelectorAll(".warning-text"); | ||
| const signUpBtn = document.querySelector(".form-btn"); | ||
| const eyesIcons = document.querySelectorAll(".eye-icon"); | ||
|
|
||
| // 유효성 검사 핸들러 | ||
| const handleValidation = (type, index) => { | ||
| const result = validInput[type](formElements[type], formElements.pw?.value); | ||
| updateValidationUI(formElements[type], warningText[index], result); | ||
|
|
||
| // 비밀번호 blur 시 pwChk도 함께 검사 | ||
| if (type === "pw" && formElements.pwChk.value) { | ||
| const chkResult = validInput.pwChk( | ||
| formElements.pwChk, | ||
| formElements.pw.value | ||
| ); | ||
| updateValidationUI(formElements.pwChk, warningText[3], chkResult); | ||
| } | ||
| checkButtonActivation(signUpBtn, "signup"); | ||
| }; | ||
|
|
||
| // 이벤트 연결 | ||
| formElements.email.addEventListener("blur", () => handleValidation("email", 0)); | ||
| formElements.nickname.addEventListener("blur", () => | ||
| handleValidation("nickname", 1) | ||
| ); | ||
| formElements.pw.addEventListener("input", () => handleValidation("pw", 2)); | ||
| formElements.pwChk.addEventListener("input", () => | ||
| handleValidation("pwChk", 3) | ||
| ); | ||
|
|
||
| // 비밀번호 토글 | ||
| eyesIcons.forEach((icon) => { | ||
| icon.addEventListener("click", () => { | ||
| const target = icon.classList.contains("pw") | ||
| ? formElements.pw | ||
| : formElements.pwChk; | ||
| togglePasswordVisibility(icon, target); | ||
| }); | ||
| }); | ||
|
|
||
| // 회원가입 버튼 | ||
| signUpBtn.addEventListener("click", (e) => { | ||
| e.preventDefault(); | ||
| checkButtonActivation(signUpBtn, "signup"); | ||
| if (!signUpBtn.disabled) { | ||
| window.location.href = "../page/login.html"; | ||
| } | ||
| }); |
|
Collaborator
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. 각 함수가 적절한 수준으로 모듈화되어있네요. 굳굳! 좋습니다 :) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| // 상태 객체 | ||
| const state = { | ||
| emailValid: false, | ||
| pwValid: false, | ||
| passwordMatchValid: false, | ||
| nickNameValid: false, | ||
| }; | ||
|
|
||
| // 상태 업데이트 | ||
| const setValidationState = (key, isValid) => { | ||
| state[key] = isValid; | ||
| }; | ||
|
|
||
| // 이메일 유효성 확인 | ||
| const checkValidEmail = (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val); | ||
|
|
||
| // input 조건 확인 함수 | ||
| export const validInput = { | ||
| email: (input) => { | ||
| const val = input.value.trim(); | ||
| if (!val) { | ||
| setValidationState("emailValid", false); | ||
| return { isValid: false, msg: "이메일을 입력해주세요." }; | ||
| } | ||
| if (!checkValidEmail(val)) { | ||
| setValidationState("emailValid", false); | ||
| return { isValid: false, msg: "잘못된 이메일 형식입니다." }; | ||
| } | ||
| setValidationState("emailValid", true); | ||
| return { isValid: true, msg: "" }; | ||
| }, | ||
|
|
||
| pw: (input) => { | ||
| const val = input.value; | ||
| if (!val) { | ||
| setValidationState("pwValid", false); | ||
| return { isValid: false, msg: "비밀번호를 입력해주세요." }; | ||
| } | ||
| if (val.length < 8) { | ||
| setValidationState("pwValid", false); | ||
| return { isValid: false, msg: "비밀번호를 8자 이상 입력해주세요." }; | ||
| } | ||
| setValidationState("pwValid", true); | ||
| return { isValid: true, msg: "" }; | ||
| }, | ||
|
|
||
| pwChk: (input, pwValue) => { | ||
| const val = input.value; | ||
| if (val.length < 8) { | ||
| setValidationState("passwordMatchValid", false); | ||
| return { isValid: false, msg: "비밀번호를 8자 이상 입력해주세요." }; | ||
| } | ||
| if (val !== pwValue) { | ||
| setValidationState("passwordMatchValid", false); | ||
| return { isValid: false, msg: "비밀번호가 일치하지 않습니다." }; | ||
| } | ||
| setValidationState("passwordMatchValid", true); | ||
| return { isValid: true, msg: "" }; | ||
| }, | ||
|
|
||
| nickname: (input) => { | ||
| const val = input.value.trim(); | ||
| if (!val) { | ||
| setValidationState("nickNameValid", false); | ||
| return { isValid: false, msg: "닉네임을 입력해주세요." }; | ||
| } | ||
| setValidationState("nickNameValid", true); | ||
| return { isValid: true, msg: "" }; | ||
| }, | ||
| }; | ||
|
|
||
| // UI 업데이트 함수 | ||
| export const updateValidationUI = (inputEle, warningMsg, { isValid, msg }) => { | ||
| inputEle.classList.toggle("input-error", !isValid); | ||
| warningMsg.innerHTML = msg; | ||
| }; | ||
|
|
||
| // 비밀번호 보기 토글 | ||
| export const togglePasswordVisibility = (buttonEl, inputEl) => { | ||
| const isActive = buttonEl.classList.toggle("on"); | ||
| inputEl.setAttribute("type", isActive ? "text" : "password"); | ||
| return isActive; | ||
| }; | ||
|
|
||
| // 버튼 활성화 체크 함수 | ||
| export const checkButtonActivation = (targetEle, pageChk) => { | ||
| const keys = | ||
| pageChk === "login" ? ["emailValid", "pwValid"] : Object.keys(state); | ||
|
|
||
| const isAllValid = keys.every((key) => state[key]); | ||
| targetEle.disabled = !isAllValid; | ||
| }; |
Uh oh!
There was an error while loading. Please reload this page.
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.
현재 각 입력 필드마다 별도의 이벤트 리스너를 설정하고 있는데, 하나의 이벤트 핸들러로 통합하고 이벤트 위임(Event Delegation) 패턴을 사용하면 코드를 더 효율적으로 만들 수 있을것같아요.
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.
먼저 폼 설정과 관련된 객체를 만들고, 초기화를 처리해서 관련있는 코드끼리 응집도를 높일수있게 처리해볼까요?
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.
그리고, 아래와 같이 하나의 이벤트 핸들러에서 위임 방식으로 이벤트를 처리해보면:
개별 입력 필드마다 별도의 이벤트 리스너를 설정하지않아도되고,
이런 장점들이 생길 수 있어요.
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.
개선으로 생길 수 있는 장점들