Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions css/auth.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import "global.css";
@import "reset.css";
@import "global.css";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿굿 ~! global.css를 후순위로 두셨군요 !

global.css를 후순위로 두셨군요 ! 이제 초기화를 한 후 전역적인 스타일을 적용되어 의도하신 우선순위대로 동작할 것으로 기대됩니다 !


.body {
display: flex;
Expand Down Expand Up @@ -51,56 +51,53 @@
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--gray100);
background-color: var(--gray-100);
border-radius: 12px;
height: 3.5rem;
padding: 1rem 1.5rem;
}

/*
:focus-within이란 - 스스로 :focus 의사 클래스와 일치하거나, 그 자손 중 하나가 :focus와 일치하는 요소를 나타냄
*/
.form__field-input-wrapper--focused:focus-within {
outline: 2px solid var(--blue100);
outline: 2px solid var(--blue-100);
}

.form__field-input {
color: var(--gray800);
color: var(--gray-800);
font-weight: 400;
background-color: var(--gray100);
background-color: var(--gray-100);
width: 100%;
}

.form__field-input::placeholder {
color: var(--gray400);
color: var(--gray-400);
}

.form__field-toggle-button {
.form__field-button {
background-color: inherit;
cursor: pointer;
}

.form__submit-button {
color: var(--gray100);
color: var(--gray-100);
font-size: 1.25rem;
font-weight: 600;
background-color: var(--blue100);
background-color: var(--blue-100);
border-radius: 2.5rem;
width: 100%;
padding: 1rem 0;
cursor: pointer;
}

.form__submit-button--disabled:disabled {
background-color: var(--gray400);
background-color: var(--gray-400);
cursor: not-allowed;
}

.social-login {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #e6f2ff;
background-color: var(--blue-50);
width: 100%;
padding: 1rem 2.5rem;
}
Expand All @@ -117,7 +114,7 @@
}

.helper-text__link {
color: var(--blue100);
color: var(--blue-100);
text-decoration: underline;
}

Expand All @@ -128,3 +125,11 @@
max-width: 400px;
}
}

.error {
outline: 2px solid var(--red);
}

.form__msg-container {
color: var(--red);
}
30 changes: 17 additions & 13 deletions css/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@
font-family: "Pretendard-Regular", sans-serif;
font-size: 16px;

--blue100: #3692ff;
--blue200: #1967d6;
--blue300: #1251aa;
--white: #ffffff;
--white-light: #fcfcfc;
--white-muted: #dfdfdf;

--blue-50: #cfe5ff;
--blue-100: #3692ff;
--blue-200: #1967d6;
--blue-300: #1251aa;

--red: #f74747;

--gray50: #f9fafb;
--gray100: #f3f4f6;
--gray200: #e5e7eb;
--gray400: #9ca3af;
--gray500: #6b7280;
--gray600: #4b5563;
--gray700: #374151;
--gray800: #1f2937;
--gray900: #111827;
--gray-50: #f9fafb;
--gray-100: #f3f4f6;
--gray-200: #e5e7eb;
--gray-400: #9ca3af;
--gray-500: #6b7280;
--gray-600: #4b5563;
--gray-700: #374151;
--gray-800: #1f2937;
--gray-900: #111827;
}

/* Tablet, Mobile 기기에 따라 폰트 크기 조정*/
@media (768px <= width < 1200px) {
:root {
font-size: 14px;
Expand Down
24 changes: 12 additions & 12 deletions css/landing.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
@import "global.css";
@import "reset.css";
@import "global.css";

.header {
background-color: #ffffff;
border-bottom: solid 1px #dfdfdf;
background-color: var(--white);
border-bottom: solid 1px var(--gray-300);
position: sticky;
top: 0px;
padding: 0.5rem 0;
Expand All @@ -24,24 +24,24 @@
justify-content: center;
align-items: center;
flex-shrink: 0;
color: #ffffff;
color: var(--white);
font-weight: 600;
background-color: var(--blue100);
background-color: var(--blue-100);
height: 48px;
width: 128px;
border-radius: 8px;
cursor: pointer;
}

.header__button--primary:visited {
color: var(--gray100);
color: var(--gray-100);
}

.hero {
display: flex;
justify-content: center;
align-items: end;
background-color: #cfe5ff;
background-color: var(--blue-50);
height: 540px;
}

Expand All @@ -63,8 +63,8 @@
}

.hero__button {
color: #ffffff;
background-color: var(--blue100);
color: var(--white);
background-color: var(--blue-100);
border-radius: 40px;
padding: 1.25rem 7.5rem;
cursor: pointer;
Expand Down Expand Up @@ -96,7 +96,7 @@
display: flex;
justify-content: space-evenly;
align-items: center;
background-color: #fcfcfc;
background-color: var(--white-light);
gap: 2.5rem;
padding: 0 1rem;
}
Expand Down Expand Up @@ -150,8 +150,8 @@

.footer {
font-weight: 400;
color: var(--gray400);
background-color: var(--gray900);
color: var(--gray-400);
background-color: var(--gray-900);
height: 160px;
padding-top: 40px;
}
Expand Down
116 changes: 105 additions & 11 deletions js/auth.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,112 @@
import { isEmpty } from "./utils.js";
import {
isEmpty,
isEmailValid,
isPwdValid,
applyClass,
removeClass,
} from "./utils.js";

const ERROR_EMAIL_EMPTY = "이메일을 입력해주세요.";
const ERROR_EMAIL_PATTERN = "잘못된 이메일 형식입니다.";
const ERROR_PASSWORD_EMPTY = "비밀번호를 입력해주세요.";
const ERROR_PASSWORD_PATTERN = "비밀번호를 8자 이상 입력해주세요.";
Comment on lines +9 to +12
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(제안) 해당 상수들은 객체로 선언해볼 수 있습니다 ! 😊:

Suggested change
const ERROR_EMAIL_EMPTY = "이메일을 입력해주세요.";
const ERROR_EMAIL_PATTERN = "잘못된 이메일 형식입니다.";
const ERROR_PASSWORD_EMPTY = "비밀번호를 입력해주세요.";
const ERROR_PASSWORD_PATTERN = "비밀번호를 8자 이상 입력해주세요.";
ERROR_MESSAGES: {
email: {
empty: "이메일을 입력해주세요.",
invalid: "잘못된 이메일 형식입니다.",
},
password: {
empty: "비밀번호를 입력해주세요.",
invalid: "비밀번호를 8자 이상 입력해주세요.",
},
};

한 곳에서 관리하고 스코프를 나누어 관리할 수 있어요 !


const IMG_VISIBLE_ON = "../assets/ic_visibility_on.svg";
const IMG_VISIBLE_OFF = "../assets/ic_visibility_off.svg";

const formInputWrappers = document.querySelectorAll(
".form__field-input-wrapper"
);
const formInputs = document.querySelectorAll(".form__field-input");
const submitButton = document.querySelector(".form__submit-button--disabled");
const submitButton = document.querySelector(".form__submit-button");
const emailInput = document.querySelector("#email");
const emailInputWrapper = document.querySelector(
".form__field-input-wrapper--email"
);
const emailMsgContainer = document.querySelector(".form__msg-container--email");
const pwdInput = document.querySelector("#password");
const pwdInputWrapper = document.querySelector(
".form__field-input-wrapper--password"
);
const pwdMsgContainer = document.querySelector(
".form__msg-container--password"
);

const pwdVisiblityButton = document.querySelector(
".form__field-button.form__field-button--password"
);
const pwdVisiblityButtonImg = document.querySelector(
".form__field-image.form__field-image--password"
);

const handleInputFocusin = () => {
submitButton.disabled = true;
};

formInputs.forEach((inputNode) =>
inputNode.addEventListener("focusin", handleInputFocusin)
);

export const isFormValid = () => {
const isInputsEmpty = Array.from(formInputs).some((input) =>
isEmpty(input.value)
);
const isInputsValid = Array.from(formInputWrappers).every(
(input) => !input.classList.contains("error")
);

return !isInputsEmpty && isInputsValid;
};

const updateSubmitButton = () => {
const isFormFilled = Array.from(formInputs)
.map((input) => input.value)
.every((string) => !isEmpty(string));
const handleEmailFocusout = (e) => {
const email = e.target.value;

submitButton.disabled = !isFormFilled;
if (!isEmailValid(email)) {
applyClass(emailInputWrapper, "error");
emailMsgContainer.textContent = isEmpty(email)
? ERROR_EMAIL_EMPTY
: ERROR_EMAIL_PATTERN;
return;
} else {
removeClass(emailInputWrapper, "error");
Comment on lines +65 to +71
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applyClass, removeClass .. 유틸 함수도 만드셨군요 😊

굿굿. 엘리먼트와 클래스명을 받아서 클래스 이름을 추가/삭제 하는 역할로 보이네요.
응용력이 좋으십니다. 👍👍

emailMsgContainer.textContent = "";
}

submitButton.disabled = !isFormValid();
};
Comment on lines +61 to +76
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호. 이벤트 핸들러 함수와 유효성 검사 함수를 분리하셨군요?

함수들의 목표가 명확하군요 👍


const handlePwdFocusout = (e) => {
const pwd = e.target.value;

if (!isPwdValid(pwd)) {
applyClass(pwdInputWrapper, "error");
pwdMsgContainer.textContent = isEmpty(pwd)
? ERROR_PASSWORD_EMPTY
: ERROR_PASSWORD_PATTERN;
return;
} else {
removeClass(pwdInputWrapper, "error");
pwdMsgContainer.textContent = "";
}

submitButton.disabled = !isFormValid();
};

formInputs.forEach((input) => {
input.addEventListener("input", updateSubmitButton);
});
emailInput.addEventListener("focusout", handleEmailFocusout);
pwdInput.addEventListener("focusout", handlePwdFocusout);

export const createVisibilityToggleHandler = (input, image) => {
let visible = false;

return function onClickToggleButton() {
visible = !visible;

input.type = visible ? "text" : "password";
image.src = visible ? IMG_VISIBLE_ON : IMG_VISIBLE_OFF;
};
Comment on lines +99 to +106
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(선택/의견/제안) 클로저 활용까지 !

visible을 함수 바깥에 설정하여 클로저를 활용하여 디스플레이를 변경하고 있군요 !
장단점이 있으므로 선택적 제안을 드리자면 data-attribute를 사용해볼 수 도 있을 것 같아요.

Suggested change
let visible = false;
return function onClickToggleButton() {
visible = !visible;
input.type = visible ? "text" : "password";
image.src = visible ? IMG_VISIBLE_ON : IMG_VISIBLE_OFF;
};
export const toggleVisibility = (input, image) => {
const isVisible = input.getAttribute("data-visible") === "true";
const nextState = !isVisible;
input.type = nextState ? "text" : "password";
image.src = nextState ? IMG_VISIBLE_ON : IMG_VISIBLE_OFF;
input.setAttribute("data-visible", nextState);
};

};

updateSubmitButton();
pwdVisiblityButton.addEventListener(
"click",
createVisibilityToggleHandler(pwdInput, pwdVisiblityButtonImg)
);
Loading
Loading