From 3b367537ba97b7a93919e16858337117844b966b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=84=B1=EC=A3=BC?= Date: Wed, 30 Apr 2025 14:27:20 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feature:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit index.html -시안대로 검사 실패 메세지 발생 시 인풋 간 거리 50px 없을 때 24px 간격 유지, 토글 아이콘도 같이 이동할 수 있게 컨테이너 추가 -
action속성 추가 login.css -유효성 검사 실패 클래스 추가 (.error-message, .error-Line, .pass-button,.pass-button:hover) -기존 버튼 색 --secondary-gray400으로 변경. validation.js,toggle-visibility-pw.js -러프하게 기능 구현 --- login/index.html | 14 ++++--- login/login.css | 41 ++++++++++++++++---- login/toggle-visibility-pw.js | 38 ++++++++++++++++++ login/validation.js | 73 +++++++++++++++++++++++++++++++++++ sign_up/index.html | 22 ++++++----- sign_up/sign-up.css | 14 ++----- 6 files changed, 170 insertions(+), 32 deletions(-) create mode 100644 login/toggle-visibility-pw.js create mode 100644 login/validation.js diff --git a/login/index.html b/login/index.html index 74734f3f..a49439dd 100755 --- a/login/index.html +++ b/login/index.html @@ -16,14 +16,16 @@ 판다마켓 로고 - +
- - - - +
+ + + + +
-
+
- - - - - - - - +
+ + + + +
+
+ + + + +
- +
@@ -45,7 +46,5 @@ - - diff --git a/login/login-main.js b/login/login-main.js new file mode 100644 index 00000000..b2511944 --- /dev/null +++ b/login/login-main.js @@ -0,0 +1,9 @@ +import { createValidRule, ruleObj, emailInput, passwordInput } from '/modules/validationRule.mjs'; +import { initValidation } from '/modules/validate.mjs' +import { initPasswordVisibility, visibilityPw } from '/modules/toggle-visibility-pw.mjs'; + +document.addEventListener('DOMContentLoaded', () => { + const validRule = createValidRule({ emailInput, passwordInput }, ruleObj); + initValidation(validRule); + initPasswordVisibility(visibilityPw); +}); diff --git a/login/validation.js b/login/validation.js deleted file mode 100644 index 6701450c..00000000 --- a/login/validation.js +++ /dev/null @@ -1,73 +0,0 @@ - -const emailInput = document.querySelector("#user-email"); -const pwInput = document.querySelector("#user-password"); -const userForm = document.querySelector("form"); -const submitBtn = document.querySelector("button"); -const errMsg = document.querySelector(".error-message"); -const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - - -function emailValidation() { - document.querySelector("#user-email+.error-message")?.remove(); - if (!regex.test(emailInput.value)) { - emailInput.classList.add("error-Line"); - const errEmail = document.createElement("span"); - errEmail.classList.add("error-message"); - errEmail.innerText = emailInput.value ? "잘못된 이메일입니다." : "이메일을 입력해주세요"; - emailInput.insertAdjacentElement("afterend", errEmail); - return false; - } else { - emailInput.classList.remove("error-Line"); - return true; - } -} - -function pwValidation() { - document.querySelector("#user-password+.error-message")?.remove(); - if (pwInput.value.length < 8) { - pwInput.classList.add("error-Line"); - const errPw = document.createElement("span"); - errPw.classList.add("error-message"); - errPw.innerText = (pwInput.value.length == 0) ? "비밀번호를 입력해주세요." : "비밀번호를 8자 이상 입력해주세요." - pwInput.insertAdjacentElement("afterend", errPw); - return false; - } else { - pwInput.classList.remove("error-Line"); - return true; - } -} - -function preventInvalidSubmit(e) { - const emailPass = emailValidation(); - const pwPass = pwValidation(); - if (!(emailPass && pwPass)) { - e.preventDefault(); - } -} - -// 이건 확실히 상태로 하는 게 좋겠네 -function canISubmit() { - const emailPass = emailValidation(); - const pwPass = pwValidation(); - // const emailPass = obj.email; - // const pwPass = obj.password; - if (!(emailPass && pwPass)) { - submitBtn.classList.add("error-button"); - } else { - submitBtn.classList.remove("error-button"); - } - // errMsg ? submitBtn.classList.add("error-button") : submitBtn.classList.remove("error-button"); -} - -emailInput.addEventListener("focusout",emailValidation); -emailInput.addEventListener("focusout",canISubmit); -pwInput.addEventListener("focusout", pwValidation); -pwInput.addEventListener("focusout", canISubmit); -userForm.addEventListener("submit", preventInvalidSubmit); -userForm.addEventListener("submit", canISubmit); - -// 추가할 내용 -// if(nameInput) -// if(pwCheckInput) - - diff --git a/login/toggle-visibility-pw.js b/modules/toggle-visibility-pw.mjs similarity index 72% rename from login/toggle-visibility-pw.js rename to modules/toggle-visibility-pw.mjs index cf2716e2..9dbf7385 100644 --- a/login/toggle-visibility-pw.js +++ b/modules/toggle-visibility-pw.mjs @@ -1,10 +1,10 @@ // #toggle-visibility-pw 관련 변수 -const visibilityPw = document.querySelector("#toggle-visibility-pw"); +export const visibilityPw = document.querySelector("#toggle-visibility-pw"); const visibilityPwLabel = document.querySelector("label[for='toggle-visibility-pw']"); const passwordInput = document.querySelector("#user-password"); // #toggle-visibility-pwcheck 관련 변수 -const visibilityPwCheck = document.querySelector("#toggle-visibility-pwcheck"); +export const visibilityPwCheck = document.querySelector("#toggle-visibility-pwcheck"); const visibilityPwCheckLabel = document.querySelector("label[for='toggle-visibility-pwcheck']"); const pwCheckInput = document.querySelector("#user-password-check"); @@ -31,8 +31,7 @@ function toggleVisibilityPwCheck() { } } -visibilityPw.addEventListener("click", toggleVisibilityPw); -if (visibilityPwCheck) visibilityPwCheck.addEventListener("click", toggleVisibilityPwCheck); - - - +export function initPasswordVisibility(visibilityPw, visibilityPwCheck){ + visibilityPw.addEventListener("click", toggleVisibilityPw); + if (visibilityPwCheck) visibilityPwCheck.addEventListener("click", toggleVisibilityPwCheck); +} diff --git a/modules/validate.mjs b/modules/validate.mjs new file mode 100644 index 00000000..82b31e9a --- /dev/null +++ b/modules/validate.mjs @@ -0,0 +1,62 @@ +const userForm = document.querySelector("form"); +const submitBtn = document.querySelector("button"); + +// 유효성 검사 전부 통과했나요? +function hasInvalidInput(validRule) { + return Object.values(validRule).some(validator => validator.passed == false) +} + +//폼 전송 막기 +function preventInvalidSubmit(e, validRule) { + //서브밋 누르면 통과 못한 인풋에 경고 보여줘 + Object.values(validRule).forEach((validator) => { + updateFailStyle({ currentTarget: validator.input }, validRule) + }); + + if (hasInvalidInput(validRule)) { + e.preventDefault(); + } +} + +//검사 실패 시 스타일 추가 +function updateFailStyle(e, validRule) { + const { name } = e.currentTarget + const validator = validRule[name]; + + document.querySelector(`#${name}+.error-message`)?.remove(); + + if (!validator.condition()) { + validator.input.classList.add("error-Line"); + const err = document.createElement("span"); + err.classList.add("error-message"); + err.innerText = validator.createMsg(); + validator.input.insertAdjacentElement("afterend", err); + validator.passed = false; + } else { + validator.input.classList.remove("error-Line"); + validator.passed = true; + } + + updateButton(validRule) +} + +// 버튼 스타일 추가 +function updateButton(validRule) { + submitBtn.classList.toggle("pass-button", !hasInvalidInput(validRule)); +} + +///리스너 추가 +export function initValidation(validRule) { + for (let validator in validRule) { + validRule[validator].input.addEventListener("focusout", e => updateFailStyle(e, validRule)); + } + + userForm.addEventListener("submit", e => preventInvalidSubmit(e, validRule)); + + if (validRule['user-password-check']) { + validRule['user-password'].input.addEventListener("focusout", () => { + // 비밀번호 변경되었을 때 비밀번호 확인도 같이 + updateFailStyle({ currentTarget: validRule['user-password-check'].input }, validRule); + }); + } +} diff --git a/modules/validationRule.mjs b/modules/validationRule.mjs new file mode 100644 index 00000000..09c2d23a --- /dev/null +++ b/modules/validationRule.mjs @@ -0,0 +1,60 @@ +export const emailInput = document.querySelector("#user-email"); +export const passwordInput = document.querySelector("#user-password"); +export const nameInput = document.querySelector("#user-name"); +export const passwordCheckInput = document.querySelector("#user-password-check"); + +// 전체 검사 조건 +export const ruleObj = { + 'user-email': { + input: emailInput, + isValid() { + return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.input.value); + }, + getErrorMessage() { + return this.input.value ? "잘못된 이메일입니다." : "이메일을 입력해주세요" + }, + }, + 'user-password': { + input: passwordInput, + isValid() { + return this.input.value.length >= 8; + }, + getErrorMessage() { + return (this.input.value.length == 0) ? "비밀번호를 입력해주세요." : "비밀번호를 8자 이상 입력해주세요." + }, + }, + 'user-name': { + input: nameInput, + isValid() { + return this.input.value; + }, + getErrorMessage() { + return "닉네임을 입력해주세요"; + }, + }, + 'user-password-check': { + input: passwordCheckInput, + isValid() { + return (passwordInput.value === this.input.value) && passwordCheckInput.value.length != 0; + }, + getErrorMessage() { + return "비밀번호가 일치하지 않습니다." + }, + } +} + +// 해당 페이지에 있는 인풋만 규칙 만들기 +export function createValidRule(inputElement, ruleObj) { + const validRule = {} + + Object.values(inputElement).forEach((input) => { + validRule[input.name] = { + input, + condition: ruleObj[input.name].isValid, + createMsg: ruleObj[input.name].getErrorMessage, + passed: false, + } + }); + + return validRule; +} \ No newline at end of file diff --git a/sign_up/index.html b/sign_up/index.html index 92c07fbb..a3029de9 100644 --- a/sign_up/index.html +++ b/sign_up/index.html @@ -7,6 +7,7 @@ +
@@ -16,7 +17,7 @@ 판다마켓 로고 -