Skip to content

Conversation

@KSJ27
Copy link
Collaborator

@KSJ27 KSJ27 commented Jan 20, 2025

요구사항

기본

로그인

  • 이메일 input에서 focus out 할 때, 값이 없을 경우 input에 빨강색 테두리와 아래에 “이메일을 입력해주세요.” 빨강색 에러 메세지를 보입니다.
  • 이메일 input에서 focus out 할 때, 이메일 형식에 맞지 않는 경우 input에 빨강색 테두리와 아래에 “잘못된 이메일 형식입니다” 빨강색 에러 메세지를 보입니다.
  • 비밀번호 input에서 focus out 할 때, 값이 없을 경우 아래에 “비밀번호를 입력해주세요.” 에러 메세지를 보입니다
  • 비밀번호 input에서 focus out 할 때, 값이 8자 미만일 경우 아래에 “비밀번호를 8자 이상 입력해주세요.” 에러 메세지를 보입니다.
  • input 에 빈 값이 있거나 에러 메세지가 있으면 ‘로그인’ 버튼은 비활성화 됩니다.
  • input 에 유효한 값을 입력하면 ‘로그인' 버튼이 활성화 됩니다.
  • 활성화된 ‘로그인’ 버튼을 누르면 “/items” 로 이동합니다

회원가입

  • 이메일 input에서 focus out 할 때, 값이 없을 경우 input에 빨강색 테두리와 아래에 “이메일을 입력해주세요.” 빨강색 에러 메세지를 보입니다.
  • 이메일 input에서 focus out 할 때, 이메일 형식에 맞지 않는 경우 input에 빨강색 테두리와 아래에 “잘못된 이메일 형식입니다” 빨강색 에러 메세지를 보입니다.
  • 닉네임 input에서 focus out 할 때, 값이 없을 경우 input에 빨강색 테두리와 아래에 “닉네임을 입력해주세요.” 빨강색 에러 메세지를 보입니다.
  • 비밀번호 input에서 focus out 할 때, 값이 없을 경우 아래에 “비밀번호를 입력해주세요.” 에러 메세지를 보입니다
  • 비밀번호 input에서 focus out 할 때, 값이 8자 미만일 경우 아래에 “비밀번호를 8자 이상 입력해주세요.” 에러 메세지를 보입니다.
  • 비밀번호 input과 비밀번호 확인 input의 값이 다른 경우, 비밀번호 확인 input 아래에 “비밀번호가 일치하지 않습니다..” 에러 메세지를 보입니다.
  • input 에 빈 값이 있거나 에러 메세지가 있으면 ‘회원가입’ 버튼은 비활성화 됩니다.
  • input 에 유효한 값을 입력하면 ‘회원가입' 버튼이 활성화 됩니다.
  • 활성화된 ‘회원가입’ 버튼을 누르면 “/signup” 로 이동합니다

심화

  • 눈 모양 아이콘 클릭시 비밀번호의 문자열이 보이기도 하고, 가려지기도 합니다.
  • 비밀번호의 문자열이 가려질 때는 눈 모양 아이콘에는 사선이 그어져있고, 비밀번호의 문자열이 보일 때는 사선이 없는 눈 모양 아이콘이 보이도록 합니다.

주요 변경사항

멘토에게

  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

@KSJ27 KSJ27 closed this Jan 20, 2025
@KSJ27 KSJ27 changed the title [강석준] sprint4 [강석준] sprint4 - 잘못된 PR입니다. Jan 20, 2025
@KSJ27 KSJ27 reopened this Jan 20, 2025
@KSJ27 KSJ27 changed the base branch from main to Basic-강석준 January 20, 2025 12:54
@KSJ27 KSJ27 changed the title [강석준] sprint4 - 잘못된 PR입니다. [강석준] sprint4 Jan 20, 2025
@KSJ27 KSJ27 added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label Jan 20, 2025
@KSJ27 KSJ27 requested a review from kiJu2 January 20, 2025 12:58
@kiJu2
Copy link
Collaborator

kiJu2 commented Jan 22, 2025

스프리트 미션 하시느라 수고 많으셨어요.
학습에 도움 되실 수 있게 꼼꼼히 리뷰 하도록 해보겠습니다. 😊

@@ -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를 후순위로 두셨군요 ! 이제 초기화를 한 후 전역적인 스타일을 적용되어 의도하신 우선순위대로 동작할 것으로 기대됩니다 !

Comment on lines +9 to +12
const ERROR_EMAIL_EMPTY = "이메일을 입력해주세요.";
const ERROR_EMAIL_PATTERN = "잘못된 이메일 형식입니다.";
const ERROR_PASSWORD_EMPTY = "비밀번호를 입력해주세요.";
const ERROR_PASSWORD_PATTERN = "비밀번호를 8자 이상 입력해주세요.";
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자 이상 입력해주세요.",
},
};

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

Comment on lines +61 to +76
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");
emailMsgContainer.textContent = "";
}

submitButton.disabled = !isFormValid();
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

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

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

Comment on lines +65 to +71
applyClass(emailInputWrapper, "error");
emailMsgContainer.textContent = isEmpty(email)
? ERROR_EMAIL_EMPTY
: ERROR_EMAIL_PATTERN;
return;
} else {
removeClass(emailInputWrapper, "error");
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 .. 유틸 함수도 만드셨군요 😊

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

Comment on lines +99 to +106
let visible = false;

return function onClickToggleButton() {
visible = !visible;

input.type = visible ? "text" : "password";
image.src = visible ? IMG_VISIBLE_ON : IMG_VISIBLE_OFF;
};
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);
};

Comment on lines +47 to +61
const handleConfirmPwdFocusout = (e) => {
const pwd = pwdInput.value;
const confirmPwd = e.target.value;

if (!isPwdMatched(pwd, confirmPwd)) {
applyClass(confirmPwdInputWrapper, "error");
confirmPwdMsgContainer.textContent = ERROR_PASSWORD_MISMATCH;
return;
} else {
removeClass(confirmPwdInputWrapper, "error");
confirmPwdMsgContainer.textContent = "";
}

submitButton.disabled = !isFormValid();
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

(선택) 이미 ifreturn을 해주고 있기 때문에 else는 불필요해보입니다 !

Suggested change
const handleConfirmPwdFocusout = (e) => {
const pwd = pwdInput.value;
const confirmPwd = e.target.value;
if (!isPwdMatched(pwd, confirmPwd)) {
applyClass(confirmPwdInputWrapper, "error");
confirmPwdMsgContainer.textContent = ERROR_PASSWORD_MISMATCH;
return;
} else {
removeClass(confirmPwdInputWrapper, "error");
confirmPwdMsgContainer.textContent = "";
}
submitButton.disabled = !isFormValid();
};
const handleConfirmPwdFocusout = (e) => {
const pwd = pwdInput.value;
const confirmPwd = e.target.value;
if (!isPwdMatched(pwd, confirmPwd)) {
applyClass(confirmPwdInputWrapper, "error");
confirmPwdMsgContainer.textContent = ERROR_PASSWORD_MISMATCH;
return;
}
removeClass(confirmPwdInputWrapper, "error");
confirmPwdMsgContainer.textContent = "";
submitButton.disabled = !isFormValid();
};

Comment on lines +5 to +7
export const isEmailValid = (email) => emailRegex.test(email);
export const isPwdValid = (pwd) => pwdRegex.test(pwd);
export const isPwdMatched = (pwd, confirm) => pwd === confirm;
Copy link
Collaborator

Choose a reason for hiding this comment

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

크으.. 간결하고 컴팩트한 순수함수들 👍

순수함수: 순수 함수는 오직 함수의 입력만이 함수의 결과에 영향을 주며 사이드이펙트가 없는 함수예요.

@kiJu2
Copy link
Collaborator

kiJu2 commented Jan 22, 2025

우아 어째 칭찬만 하다가 끝나버렸어요.
석준님 응용력이 좋으신데요 ?
고급 패턴들 또한 익히시면 상당히 잘 응용하실 것 같아요.
리액트에서는 어떻게 코드를 작성하실지 궁금합니다 🤩🤩

미션 수행하시느라 정말 수고 많으셨습니다 석준님 ! 👍👍

@kiJu2 kiJu2 merged commit 1aff0e0 into codeit-bootcamp-frontend:Basic-강석준 Jan 22, 2025
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants