-
Notifications
You must be signed in to change notification settings - Fork 57
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
[Week4] 권부근 #133
The head ref may contain hidden characters: "part1-\uAD8C\uBD80\uADFC-Week4"
[Week4] 권부근 #133
Changes from all commits
87e3f15
753e5ff
ab63402
f9eca34
7c4fc07
c115edc
10c60ef
56cd508
916de49
5bb500a
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,14 @@ | ||
name: delete branch on close pr | ||
|
||
on: | ||
pull_request: | ||
types: [closed] | ||
|
||
jobs: | ||
delete-branch: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: delete branch | ||
uses: SvanBoxel/delete-merged-branch@main | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { | ||
displayError, | ||
resetError, | ||
validateInput, | ||
validationState, | ||
} from "./utill/validation.js"; | ||
import { ERROR_MESSAGE } from "./utill/constant.js"; | ||
import { user } from "./utill/db.js"; | ||
|
||
const form = document.querySelector(".sign-form"); | ||
const inputs = form.querySelectorAll("input"); | ||
|
||
const submit = document.querySelector(".cta"); | ||
soonoo27 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const authType = submit.dataset.auth; | ||
|
||
const emailInput = document.querySelector('.sign-input[type="email"]'); | ||
const passwordInput = document.querySelector('.sign-input[type="password"]'); | ||
const confirmPasswordInput = document.querySelector(".confirm-password"); | ||
|
||
const focusHandler = (e) => { | ||
if (e.target.tagName === "INPUT") { | ||
const errorMessage = validateInput(e.target); | ||
displayError(e.target, errorMessage); | ||
} | ||
}; | ||
Comment on lines
+20
to
+25
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. 저는 mousedown, focusout, mouseup, click 이벤트의 처리 순서를 이용한 방법을 생각해봤습니다. (링크) focusout 이벤트를 핸들러를 폼에 추가하고, 타겟이 input일 때만 처리하도록 구현하셨군요 👍 |
||
|
||
const submitHandler = (e) => { | ||
e.preventDefault(); | ||
resetError(); | ||
let isValid = true; | ||
let account = {}; | ||
|
||
inputs.forEach((input) => { | ||
const { type, value, name } = input; | ||
if (validationState[name] === undefined) { | ||
const errorMessage = validateInput(input); | ||
if (errorMessage) { | ||
displayError(input, errorMessage); | ||
isValid = false; | ||
} | ||
} else if (!validationState[name]) { | ||
displayError( | ||
input, | ||
ERROR_MESSAGE[authType]["INVALID_" + type.toUpperCase()] | ||
); | ||
isValid = false; | ||
} | ||
account[name] = value; | ||
}); | ||
|
||
let isSubmit = false; | ||
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. (지극히 개인적인 의견) shouldSubmit이 의미를 더 명확하게 나타내는 이름 같아요. boolean 변수 네이밍 관련해서 읽어보면 좋은 글: |
||
|
||
if (authType === "signin" && isValid) { | ||
if (account.email !== user.email) { | ||
displayError(emailInput, ERROR_MESSAGE[authType]["INVALID_EMAIL"]); | ||
isValid = false; | ||
} else if (account.password !== user.password) { | ||
console.log(account, user); | ||
displayError(passwordInput, ERROR_MESSAGE[authType]["INVALID_PASSWORD"]); | ||
isValid = false; | ||
} else { | ||
isSubmit = true; | ||
} | ||
} | ||
|
||
if (authType === "signup" && isValid) { | ||
if (account.email === user.email) { | ||
displayError(emailInput, ERROR_MESSAGE[authType]["EXIST_EMAIL"]); | ||
isValid = false; | ||
} else if (passwordInput.value !== confirmPasswordInput.value) { | ||
displayError( | ||
confirmPasswordInput, | ||
ERROR_MESSAGE[authType]["PASSWORD_EQUAL"] | ||
); | ||
isValid = false; | ||
} | ||
if (isValid) { | ||
isSubmit = true; | ||
} | ||
} | ||
if (isSubmit) { | ||
form.submit(); | ||
} | ||
}; | ||
|
||
const keyupHandler = (e) => { | ||
if (e.key === "Enter") { | ||
submit.click(); | ||
} | ||
Comment on lines
+87
to
+89
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. 사용성을 고려한 구현 좋네요 💯 그리고 keyupHandler가 document에 추가되어 있어서 아무데서나 엔터 키를 눌러도 폼이 전송되네요. 이부분은 개선될 여지가 있어 보입니다! (의도하신게 아니라면) |
||
}; | ||
|
||
form.addEventListener("focusout", focusHandler); | ||
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.
|
||
form.addEventListener("submit", submitHandler); | ||
document.addEventListener("keyup", keyupHandler); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,21 +26,25 @@ | |
</p> | ||
</header> | ||
<div class="sign-box"> | ||
<form class="sign-form"> | ||
<form action="/folder.html" class="sign-form" novalidate> | ||
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. 자체 유효성 검사를 사용하고 있으니 novalidate 속성 사용 좋네요! |
||
<div class="sign-inputs"> | ||
<div class="sign-input-box"> | ||
<label class="sign-input-label">이메일</label> | ||
<input class="sign-input" /> | ||
<input class="sign-input" type="email" name="email" /> | ||
</div> | ||
<div class="sign-input-box sign-password"> | ||
<div class="error-message"></div> | ||
<div class="sign-input-box"> | ||
<label class="sign-input-label">비밀번호</label> | ||
<input class="sign-input" type="password" /> | ||
<button class="eye-button" type="button"> | ||
<img src="../images/eye-off.svg" /> | ||
</button> | ||
<div class="sign-password"> | ||
<input class="sign-input" type="password" name="password" /> | ||
<button class="eye-button" type="button"> | ||
<img src="../images/eye-off.svg" /> | ||
</button> | ||
</div> | ||
<div class="error-message"></div> | ||
</div> | ||
</div> | ||
<button class="cta" type="submit">로그인</button> | ||
<button class="cta" type="submit" data-auth="signin">로그인</button> | ||
</form> | ||
<div class="sns-box"> | ||
<span class="sns-text">소셜 로그인</span> | ||
|
@@ -54,5 +58,7 @@ | |
</div> | ||
</div> | ||
</div> | ||
<script type="module" src="main.js"></script> | ||
<script src="./utill/toggle.js"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export const ERROR_MESSAGE = { | ||
signin: { | ||
EMPTY_EMAIL: "이메일을 입력해주세요.", | ||
EMPTY_PASSWORD: "비밀번호를 입력해주세요.", | ||
INVALID_EMAIL: "이메일을 확인해주세요", | ||
INVALID_PASSWORD: "비밀번호를 확인해주세요.", | ||
}, | ||
signup: { | ||
EMPTY_EMAIL: "이메일을 입력해주세요.", | ||
EMPTY_PASSWORD: "비밀번호를 입력해주세요.", | ||
INVALID_EMAIL: "올바른 이메일 주소가 아닙니다.", | ||
INVALID_PASSWORD: "비밀번호는 영문, 숫자 조합 8자 이상 입력해 주세요.", | ||
EXIST_EMAIL: "이미 존재하는 이메일입니다.", | ||
PASSWORD_EQUAL: "비밀번호가 일치하지 않아요.", | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const user = { | ||
email: "[email protected]", | ||
password: "codeit101", | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
document.querySelectorAll(".eye-button").forEach((button) => { | ||
button.addEventListener("click", function () { | ||
const input = this.previousElementSibling; | ||
const img = this.querySelector("img"); | ||
|
||
if (input.type === "password") { | ||
input.type = "text"; | ||
img.src = "../images/eye-on.svg"; | ||
} else { | ||
input.type = "password"; | ||
img.src = "../images/eye-off.svg"; | ||
Comment on lines
+6
to
+11
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,50 @@ | ||
// validation.js | ||
import { ERROR_MESSAGE } from "./constant.js"; | ||
import { user } from "./db.js"; | ||
|
||
const submit = document.querySelector(".cta"); | ||
const authType = submit.dataset.auth; | ||
|
||
export const validationState = {}; | ||
|
||
const PATTERN = { | ||
email: | ||
/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i, | ||
password: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/, | ||
"confirm-password": /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/, | ||
}; | ||
|
||
const getErrorMessage = (name, condition) => { | ||
const errorType = condition ? "EMPTY_" : "INVALID_"; | ||
return ERROR_MESSAGE[authType][errorType + name.toUpperCase()]; | ||
}; | ||
|
||
export function validateInput(input) { | ||
const { name, value } = input; | ||
let errorMessage = ""; | ||
|
||
if (value === "") { | ||
errorMessage = getErrorMessage(name, true); | ||
} else if (!PATTERN[name].test(value)) { | ||
errorMessage = getErrorMessage(name, false); | ||
} else if ( | ||
authType === "signup" && | ||
name === "email" && | ||
value === user.email | ||
) { | ||
errorMessage = ERROR_MESSAGE[authType]["EXIST_EMAIL"]; | ||
} | ||
|
||
validationState[name] = !errorMessage; | ||
|
||
return errorMessage; | ||
} | ||
|
||
export function resetError() { | ||
const errorMessages = document.querySelectorAll(".error-message"); | ||
errorMessages.forEach((message) => (message.textContent = "")); | ||
} | ||
export function displayError(input, errorMessage) { | ||
const errorDisplay = input.parentNode.nextElementSibling; | ||
errorDisplay.textContent = errorMessage; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<!DOCTYPE html> | ||
<html lang="ko"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Document</title> | ||
</head> | ||
<body> | ||
<div>folder 페이지</div> | ||
</body> | ||
</html> |
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.
input 태그로만 요소를 선택하면 추후에 다른 input 요소가 문서에 추가되었을 때 의도하지 않은 동작이 발생할 가능성이 있어 보입니다.
조금 더 구체적인 셀렉터를 사용하는건 어떨까요?