Skip to content
19 changes: 19 additions & 0 deletions assets/css/member.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@
color: var(--gray800);
}

.form__input-box .error-msg {
margin-top: var(--space-xxs);
padding: 0 var(--space-xs);
font-size: 14px;
}

/* validation 실패시 */
.form__input-box.isError .input {
border-color: var(--error);
}
.form__input-box.isError .error-msg {
color: var(--error);
}

/* validation 통과시 */
.form__input-box.isValid .input {
border-color: var(--primary-color);
}

/* 비밀번호 인풋박스박스 */
.form__input-box-pw .input-box__input {
position: relative;
Expand Down
1 change: 1 addition & 0 deletions assets/css/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
--gray700: #374151;
--gray800: #1f2937;
--gray900: #111827;
--error: #f74747;

/* space */
--space-xxs: 8px;
Expand Down
137 changes: 137 additions & 0 deletions assets/js/member.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// 에러 메세지 생성 함수
const formEl = document.querySelector(".member-box__form");
const submitBtn = document.querySelector(".member-box__form .form__submitBtn");

// 빈값일 때 메세지 지정
const EMPTY_MSG = {
nickname: "닉네임을 입력해주세요.",
email: "이메일을 입력해주세요.",
password: "비밀번호를 입력해주세요.",
passwordConfirm: "비밀번호를 입력해주세요.",
};

// validation 규칙
const VALIDATION_RULE = {
nickname: {
isValid: function (value) {
return !!value.length;
},
failedMsg: null,
},
email: {
isValid: function (value) {
const PATTERN =
/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/;
return PATTERN.test(value);
},
failedMsg: "잘못된 이메일 형식입니다.",
},
password: {
isValid: function (value) {
const PATTERN = /^[0-9a-zA-Z]{8}/;
return PATTERN.test(value);
},
failedMsg: "비밀번호를 8자 이상 입력해주세요.",
},
passwordConfirm: {
isValid: function (value) {
const password = document.querySelector("#password");
return password.value === value;
},
failedMsg: "비밀번호가 일치하지 않습니다.",
},
};

// 에러 메세지 생성
function createErrorMsg(text, inputBox) {
// 에러 메세지 중복 생성 방지
if (inputBox.querySelector(".error-msg")) return;

const msg = document.createElement("p");
msg.textContent = text;
msg.classList.add("error-msg");
inputBox.classList.add("isError");
inputBox.append(msg);
}

// input에 값 입력시 isError / isValid 초기화
function changeInputReset(e) {
const inputBox = e.target.closest(".form__input-box");

if (inputBox.classList.contains("isError")) {
inputBox.classList.remove("isError");
inputBox.querySelector(".error-msg").remove();
}

if (inputBox.classList.contains("isValid")) {
inputBox.classList.remove("isValid");
}
}

// 페이지내의 전체 input validation 통과했는지 확인
function checkAllPass() {
const inputs = document.querySelectorAll(".member-box__form .input");
const isAllPass = Array.from(inputs).every((input) =>
input.closest(".form__input-box").classList.contains("isValid")
);

submitBtn.disabled = !isAllPass;
}

// 빈값 검사
function checkEmpty(name, inputBox) {
if (!EMPTY_MSG[name]) return; // EMPTY_MSG에 유효한 값이 있는지 확인

createErrorMsg(EMPTY_MSG[name], inputBox);
}

// validation 검사
function checkValidation(value, name, inputBox) {
if (!VALIDATION_RULE[name]) return; // VALIDATION_RULE에 유효한 값이 있는지 확인

const isValid = VALIDATION_RULE[name].isValid(value); // isValid 검사

if (!isValid) {
// 항목별 validation 실패시
createErrorMsg(VALIDATION_RULE[name].failedMsg, inputBox);
} else {
// 항목별 validation 통과시
inputBox.classList.add("isValid");
}
}

// focusout 핸들링 함수
function handleFocusOut({ target }) {
if (!target.classList.contains("input")) return;
const { value, name } = target;
const inputBox = target.closest(".form__input-box");

if (!value.length) {
// 값이 없으면,
checkEmpty(name, inputBox);
} else {
// 값이 있으면,
checkValidation(value, name, inputBox);
}

// 전체 input 유효성 통과헀는지 검사
checkAllPass();
}

function togglePassword(e) {
if (!e.target.closest(".input-box__toggle")) return;
const pwBox = e.target.closest(".input-box__input");
const inputBox = pwBox.querySelector(".input");
const isShow = pwBox.classList.contains("pw_show");
pwBox.classList.toggle("pw_show");
inputBox.setAttribute("type", isShow ? "password" : "text");
}

function movePage(e) {
location.href = e.target.dataset.moveLink;
}

formEl.addEventListener("input", changeInputReset);
formEl.addEventListener("focusout", handleFocusOut);
formEl.addEventListener("click", togglePassword);
submitBtn.addEventListener("click", movePage);
16 changes: 12 additions & 4 deletions login.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ <h1 class="logo">
</div>
</div>
<div class="form__input-box form__input-box-pw">
<label for="pw" class="input-box__label">비밀번호</label>
<label for="password" class="input-box__label">비밀번호</label>
<div class="input-box__input">
<input
type="password"
name="pw"
id="pw"
name="password"
id="password"
class="input"
placeholder="비밀번호를 입력해주세요."
/>
Expand All @@ -57,7 +57,14 @@ <h1 class="logo">
</button>
</div>
</div>
<button class="btn lg form__submitBtn">로그인</button>
<button
type="button"
class="btn lg form__submitBtn"
disabled
data-move-link="/items.html"
>
로그인
</button>
</form>
<!-- form :: E -->
<!-- sns-box :: S -->
Expand Down Expand Up @@ -100,5 +107,6 @@ <h2 class="sns-box__title">간편 로그인하기</h2>
</p>
</div>
</div>
<script src="./assets/js/member.js"></script>
</body>
</html>
24 changes: 16 additions & 8 deletions signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ <h1 class="logo">
</div>
</div>
<div class="form__input-box form__input-box-pw">
<label for="pw" class="input-box__label">비밀번호</label>
<label for="password" class="input-box__label">비밀번호</label>
<div class="input-box__input">
<input
type="password"
name="pw"
id="pw"
name="password"
id="password"
class="input"
placeholder="비밀번호를 입력해주세요."
/>
Expand All @@ -69,14 +69,14 @@ <h1 class="logo">
</div>
</div>
<div class="form__input-box form__input-box-pw">
<label for="confirm_pw" class="input-box__label"
<label for="passwordConfirm" class="input-box__label"
>비밀번호 확인</label
>
<div class="input-box__input pw_show">
<div class="input-box__input">
<input
type="password"
name="confirm_pw"
id="confirm_pw"
name="passwordConfirm"
id="passwordConfirm"
class="input"
placeholder="비밀번호를 한번 더 입력해주세요."
/>
Expand All @@ -93,7 +93,14 @@ <h1 class="logo">
</button>
</div>
</div>
<button class="btn lg form__submitBtn">회원가입</button>
<button
type="button"
class="btn lg form__submitBtn"
disabled
data-move-link="/login.html"
>
회원가입
</button>
</form>
<!-- form :: E -->
<!-- sns-box :: S -->
Expand Down Expand Up @@ -136,5 +143,6 @@ <h2 class="sns-box__title">간편 로그인하기</h2>
</p>
</div>
</div>
<script src="./assets/js/member.js"></script>
</body>
</html>
Loading