-
Notifications
You must be signed in to change notification settings - Fork 39
[송시은] Sprint4 #101
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
The head ref may contain hidden characters: "Basic-\uC1A1\uC2DC\uC740-sprint4"
[송시은] Sprint4 #101
Changes from all commits
a2757e0
a8d3e05
7b3cf42
086f860
96fc74e
d3515f5
5d8bc85
c88be1e
f22a8dc
01f8f8e
99a1865
7d2facc
3181f21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
|
Collaborator
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,51 @@ | ||
| <!-- 추후 추가 수정 예정 --> | ||
|
|
||
| # 코드잇 스프린트 미션 | ||
|
|
||
| ## 미션 목록 | ||
|
|
||
| | 미션 | 날짜 | PR | 주요 내용 | | ||
| | ---- | ---------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | ||
| | 1 | 2025-02-24 | [#10](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/10) | 랜딩 페이지의 HTML 및 CSS 구현 | | ||
| | 2 | 2025-03-05 | [#44](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/44) | 회원가입 및 로그인 페이지의 HTML, CSS 구현 | | ||
| | 3 | 2025-03-07 | [#60](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/60) | 반응형 디자인 구현(desktop-first, 1920px 이상 큰 모니터 기준), breakpoint: 1919px, 1199px, 767px | | ||
| | 4 | 2025-03-18 | [#](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/) | JS기능 추가(DOM 요소 조작 및 이벤트 리스너), 회원가입, 로그인 폼 유효성 검사 | | ||
|
|
||
| --- | ||
|
|
||
| ## 컨벤션 | ||
|
|
||
| ### 명명 규칙 | ||
|
|
||
| 1. **이미지 파일**: | ||
|
|
||
| - 이미지 파일 이름은 **소문자**로 작성하고, **언더스코어(\_)**를 사용하여 단어를 구분합니다. | ||
|
|
||
| 2. **HTML, CSS, JS 파일, 폴더명**: | ||
|
|
||
| - 파일, 폴더 이름은 **소문자**로 작성하고, **하이픈(-)**을 사용하여 단어를 구분합니다.(kebab-case) | ||
|
|
||
| 3. **변수명, 함수명, 프로퍼티 키**: | ||
| - camelCase | ||
|
|
||
| ### 함수 규칙 | ||
|
|
||
| **화살표 함수**를 사용하되, this바인딩 고려 시 필요한 경우(이벤트 리스너의 콜백함수, 메소드 정의 등) 일반 함수도 사용 가능 합니다. | ||
|
|
||
| ### 커밋 규칙 | ||
|
|
||
| 1. 커밋 메시지는 소문자로 작성합니다. | ||
| 2. 커밋 메시지 본문 작성은 선택사항입니다. | ||
| 3. 타입: 내용 | ||
| | **타입** | **내용** | | ||
| |------ ---|-----------| | ||
| | **feat** | 새로운 기능 추가 | | ||
| | **fix** | 버그 수정 | | ||
| | **docs** | 문서 변경 (README, Wiki 등) | | ||
| | **style** | 코드 스타일 변경 (세미콜론, 공백, 들여쓰기 등) | | ||
| | **refactor** | 코드 리팩토링 (기능 변경 없이 코드 구조나 가독성 개선) | | ||
| | **perf** | 성능 개선 | | ||
| | **test** | 테스트 코드 추가 및 수정 | | ||
| | **chore** | 기타 일들 (빌드 스크립트, 환경 설정 등) | | ||
|
|
||
| ## 폴더 구조 |
|
Collaborator
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,151 @@ | ||||||||||||||||
| import { ERROR_MESSAGES } from '../constants/auth-validation-messages.js'; | ||||||||||||||||
|
|
||||||||||||||||
| document.addEventListener('DOMContentLoaded', function () { | ||||||||||||||||
| const form = document.querySelector('.auth-form'); | ||||||||||||||||
| const authSubmitButton = document.querySelector('.auth-button'); | ||||||||||||||||
| const emailInput = document.getElementById('email'); | ||||||||||||||||
| const passwordInput = document.getElementById('password'); | ||||||||||||||||
| const nicknameInput = document.getElementById('nickname'); | ||||||||||||||||
| const confirmPasswordInput = document.getElementById('password-confirm'); | ||||||||||||||||
| const authType = form.dataset.authType; | ||||||||||||||||
|
|
||||||||||||||||
| let emailValue; | ||||||||||||||||
| let nicknameValue; | ||||||||||||||||
| let passwordValue; | ||||||||||||||||
| let confirmPasswordValue; | ||||||||||||||||
|
|
||||||||||||||||
| // 이메일 형식 검증 | ||||||||||||||||
| const validateEmail = (email) => { | ||||||||||||||||
| const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | ||||||||||||||||
| return regex.test(String(email)); | ||||||||||||||||
| }; | ||||||||||||||||
|
Comment on lines
+18
to
+21
Collaborator
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. 💊 제안 |
||||||||||||||||
|
|
||||||||||||||||
| // 에러 메시지 표시 | ||||||||||||||||
| const toggleError = (targetInput, message, isInputValid) => { | ||||||||||||||||
| const inputContainer = targetInput.closest('.input-container'); | ||||||||||||||||
| if (!inputContainer) return; | ||||||||||||||||
| const errorContainer = inputContainer.querySelector( | ||||||||||||||||
| '.validation-error-message', | ||||||||||||||||
| ); | ||||||||||||||||
|
Comment on lines
+25
to
+29
Collaborator
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. 💊 제안
Suggested change
|
||||||||||||||||
| if (!isInputValid) { | ||||||||||||||||
| targetInput.classList.add('error-input'); | ||||||||||||||||
| errorContainer.textContent = message; | ||||||||||||||||
| errorContainer.classList.add('active'); | ||||||||||||||||
| } else { | ||||||||||||||||
| targetInput.classList.remove('error-input'); | ||||||||||||||||
| errorContainer.textContent = ''; | ||||||||||||||||
| errorContainer.classList.remove('active'); | ||||||||||||||||
| } | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| // 개별 인풋 검증: 포커스아웃된 input만 검증하고 에러 메시지 표시 | ||||||||||||||||
| const validateInput = (target) => { | ||||||||||||||||
|
Collaborator
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. 💊 제안 |
||||||||||||||||
| if (target.id === 'email') { | ||||||||||||||||
| emailValue = emailInput.value.trim(); | ||||||||||||||||
|
|
||||||||||||||||
| if (emailValue === '') { | ||||||||||||||||
| toggleError(target, ERROR_MESSAGES.emailRequired, false); | ||||||||||||||||
| } else if (!validateEmail(emailValue)) { | ||||||||||||||||
| toggleError(target, ERROR_MESSAGES.invalidEmail, false); | ||||||||||||||||
| } else { | ||||||||||||||||
| toggleError(target, '', true); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if (target.id === 'nickname' && authType === 'signup') { | ||||||||||||||||
| nicknameValue = nicknameInput.value.trim(); | ||||||||||||||||
| if (nicknameValue === '') { | ||||||||||||||||
| toggleError(target, ERROR_MESSAGES.nicknameRequired, false); | ||||||||||||||||
| } else { | ||||||||||||||||
| toggleError(target, '', true); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if (target.id === 'password') { | ||||||||||||||||
| passwordValue = passwordInput.value.trim(); | ||||||||||||||||
| if (passwordValue === '') { | ||||||||||||||||
| toggleError(target, ERROR_MESSAGES.passwordRequired, false); | ||||||||||||||||
| } else if (passwordValue.length < 8) { | ||||||||||||||||
| toggleError(target, ERROR_MESSAGES.passwordLength, false); | ||||||||||||||||
| } else { | ||||||||||||||||
| toggleError(target, '', true); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if (target.id === 'password-confirm' && authType === 'signup') { | ||||||||||||||||
| confirmPasswordValue = confirmPasswordInput.value.trim(); | ||||||||||||||||
| if (confirmPasswordValue === '') { | ||||||||||||||||
| toggleError(target, ERROR_MESSAGES.confirmPasswordRequired, false); | ||||||||||||||||
| } else if (passwordValue !== confirmPasswordValue) { | ||||||||||||||||
| toggleError(target, ERROR_MESSAGES.passwordMismatch, false); | ||||||||||||||||
| } else { | ||||||||||||||||
| toggleError(target, '', true); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| // 전체 폼 유효성 검사 | ||||||||||||||||
| const validateForm = () => { | ||||||||||||||||
| let isFormValid = true; | ||||||||||||||||
|
|
||||||||||||||||
| emailValue = emailInput.value.trim(); | ||||||||||||||||
| passwordValue = passwordInput.value.trim(); | ||||||||||||||||
| nicknameValue = nicknameInput ? nicknameInput.value.trim() : ''; | ||||||||||||||||
| confirmPasswordValue = confirmPasswordInput | ||||||||||||||||
| ? confirmPasswordInput.value.trim() | ||||||||||||||||
| : ''; | ||||||||||||||||
|
|
||||||||||||||||
| if (emailValue === '' || !validateEmail(emailValue)) isFormValid = false; | ||||||||||||||||
| if (passwordValue === '' || passwordValue.length < 8) isFormValid = false; | ||||||||||||||||
| if (authType === 'signup') { | ||||||||||||||||
| if (nicknameValue === '') isFormValid = false; | ||||||||||||||||
| if (confirmPasswordValue === '' || passwordValue !== confirmPasswordValue) | ||||||||||||||||
| isFormValid = false; | ||||||||||||||||
| } | ||||||||||||||||
| return isFormValid; | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| // 제출 버튼 활성화 상태 | ||||||||||||||||
| const updateSubmitButtonState = () => { | ||||||||||||||||
| authSubmitButton.disabled = !validateForm(); | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| // 포커스아웃 시 인풋 유효성 검사 | ||||||||||||||||
| form.addEventListener('focusout', function (event) { | ||||||||||||||||
| if (event.target.matches('input')) { | ||||||||||||||||
| validateInput(event.target); | ||||||||||||||||
| } | ||||||||||||||||
| }); | ||||||||||||||||
|
Comment on lines
+109
to
+118
Collaborator
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. 💊 제안 |
||||||||||||||||
|
|
||||||||||||||||
| // input 이벤트에 적용(input이 변할때마다 이벤트가 발생하는 것을 막기 위해 넣었지만 원리는 이해 더 필요) | ||||||||||||||||
| const debounce = (func, delay) => { | ||||||||||||||||
| let timer; | ||||||||||||||||
| return function (...args) { | ||||||||||||||||
| clearTimeout(timer); | ||||||||||||||||
| timer = setTimeout(() => { | ||||||||||||||||
| func.apply(this, args); | ||||||||||||||||
| }, delay); | ||||||||||||||||
| }; | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| // 인풋 입력 시 버튼 상태 업데이트(form이 유효성 검사를 통과하면 focus를 옮기지 않아도 자동 버튼 활성화되도록) | ||||||||||||||||
| form.addEventListener( | ||||||||||||||||
| 'input', | ||||||||||||||||
| debounce((event) => { | ||||||||||||||||
|
Collaborator
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. 💊 제안
Suggested change
|
||||||||||||||||
| updateSubmitButtonState(); | ||||||||||||||||
| }, 300), | ||||||||||||||||
| ); | ||||||||||||||||
|
|
||||||||||||||||
| // 폼 제출 시 전체 폼 검증 후 페이지 이동 처리 | ||||||||||||||||
| form.addEventListener('submit', function (event) { | ||||||||||||||||
| event.preventDefault(); | ||||||||||||||||
|
|
||||||||||||||||
| if (validateForm()) { | ||||||||||||||||
| if (authType === 'signup') { | ||||||||||||||||
|
Comment on lines
+143
to
+144
Collaborator
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. 💊 제안
Suggested change
|
||||||||||||||||
| window.location.href = '/signup'; | ||||||||||||||||
| } else if (authType === 'login') { | ||||||||||||||||
| window.location.href = '/items'; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| }); | ||||||||||||||||
| }); | ||||||||||||||||
|
Collaborator
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. 👍 칭찬 |
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.
👍 칭찬
깃에 올라가지 않을 파일을 관리해주시는 것 좋습니다~