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
18 changes: 10 additions & 8 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ <h1>일상의 모든 물건을<br>
<div class="contents0">
<img src="./image/Img_home_top.png">
</div>
</div>
</div>
</div>

<!-- main 컨테이너 -->
<div class="container1">
<div class="contents">
Expand All @@ -34,35 +35,36 @@ <h1>일상의 모든 물건을<br>
<div class="text-box">
<p class="hot-item">Hot_item</p>
<h1>
인기 상품을<br>
확인해 보세요
인기 상품을
확인해 보세요
</h1>
<p class="description">가장 HOT한 중고거래 물품을 판다 마켓에서 확인해 보세요</p>
</div>
</div>
<!-- main 컨테이너 -->
<div class="container1">
<div class="container2">
<div class="text-box2">
<h1>구매를 원하는<br> 상품을 검색하세요</h1>
<a class="Search">Search</a>
<h1>구매를 원하는 상품을 검색하세요</h1>
<p class="description">구매하고 싶은 물품은 검색해서 쉽게 찾아보세요</p>
</div>
<div class="contents">
<img src="./image/Img_home_02.png">
</div>
</div>
<!-- main 컨테이너 -->
<div class="container1">
<div class="container3">
<div class="contents">
<img src="./image/Img_home_03.png">
</div>
<div class="text-box3">
<p class="register">Register</p>
<a class="register">Register</a>
<h1>판매를 원하는<br>상품을 등록하세요</h1>
<p class="description">어떤 물건이든 판매하고 싶은 상품을 쉽게 등록하세요</p>
</div>
</div>

<div class="container2">
<div class="container4">
<!-- 텍스트와 사진 -->
<div class="inner_box">
<div text-box4>
Expand Down
13 changes: 9 additions & 4 deletions sign-in.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ <h1>판다마켓</h1>
<form>
<div class="group">
<label for="email">이메일</label>
<input type="email" id="email" name="email">
<input type="email" id="email" name="email" placeholder="이메일을 입력해주세요."
class="error-input">
<p id="emailErr" class="errMsg">잘못된 이메일 형식입니다</p>
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
미리 에러 메시지가 나타날 태그를 만들어 주셔서 DOM 조작을 최소화하신 점은 좋습니다!
다만 에러 메시지는 에러 상황에 따라 추가되도록 하는 것이 더 명확할 것 같아요!
지금처럼 미리 메시지가 들어가 있는 경우는 에러 나는 경우가 하나인 경우에 적절할 것 같습니다.


</div>
<div class="group">
<label for="password">비밀번호</label>
<div class="password-input">
<input type="password" id="password" name="password">
<input type="password" id="password" name="password" placeholder="비밀번호를 입력해주세요.">

<img src="./image/invisible_icon.png" class="password-icon" alt="비밀번호 보기">
<p id="passwordErr" class="errMsg">비밀번호를 8자 이상 입력해주세요.</p>
</div>
</div>
<button type="submit">로그인</button>
Copy link
Collaborator

Choose a reason for hiding this comment

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

❗️ 수정요청
지금은 디자인상 버튼이 회색일 뿐 제출이 되네요.
해당 버튼에 disabled 속성을 추가하셔서 input이 비어있을 때는 버튼이 비활성화되고 클릭되지 않도록 해주세요!

Expand All @@ -51,12 +56,12 @@ <h1>간편 로그인하기</h1>

</div>
<div class="footer">
<h1>판다마켓이 처음이신가요?</h1>
<p>판다마켓이 처음이신가요?</p>
<a href="./signup.html">회원가입</a>
</div>


</div>

<script src="./sign-in.js"></script>
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안

아마 script 태그를 HTML의 하단에 배치하신 이유가 script가 문서의 렌더링을 막지 않도록 하기 위해서이실 것 같아요.
하지만, script 태그에 defer나 async 속성을 사용하면 이런 문제를 해결할 수 있기 때문에 반드시 하단에 배치할 필요는 없습니다!
또한 script 태그는 상단에 있는게 구조 파악에서도 유리하기 때문에 상단 head 태그에 두시는 것을 추천드려요~

script async
script defer

지금과 같은 경우 DOM을 조작하는 JS 이니 defer 속성을 추가하시면 되겠습니다~

</body>
</html>
85 changes: 85 additions & 0 deletions sign-in.js
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
로그인에서 사용하는 js 파일과 에러메시지나 로직 측면에서 동일한 것이 많습니다~
이런 경우 중복을 줄이기 위해 반복 사용되는 함수, 정규식, 에러메시지들은 다른 파일로 분리하시고 각 js 파일에서 가져와서 사용하시는 것을 추천드려요!

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* login, signup 공통 */

// 이메일 유효성 검사 함수
function emailValidation(email) {
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return emailRegex.test(email);
}
Comment on lines +4 to +7
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
sign-up.js 파일에서도 동일한 정규식을 사용하고 있는데 그때마다 선언해서 쓰면 문제가 있을 것 같아요.
정규식을 반복해서 선언하면 유지보수가 어려워지고, 코드의 일관성이 떨어질 수 있습니다. 만약 정규식을 수정해야 할 때 여러 곳에서 변경해야 하고 실수로 서로 다른 정규식을 사용할 위험도 커집니다.
이렇게 두개의 파일에서 사용하고 있으니 해당 정규식과 test 함수를 따른 파일로 분리해 사용하시는 것을 추천드려요!


// 요소 가져오기
const emailInput = document.getElementById("email");
const passwordInput = document.getElementById("password");
const emailErr = document.getElementById("emailErr");
const passwordErr = document.getElementById("passwordErr");
const passwordVisibility = document.getElementById("passwordVisibility");
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
변수명은 해당 변수의 값의 타입을 유추할 수 있는 이름이 좋습니다. isError는 boolean값이라는 것을, emailInput은 input 태그라는 것을 알 수 있습니다. 해당 변수도 emailInput처럼 태그라는 것을 알 수 있게 변경하시는 것을 추천드려요!


// 초기 오류 메시지 숨김
emailErr.textContent = "";
passwordErr.textContent = "";

// 이메일 검증
function validateEmail() {
const emailValue = emailInput.value.trim();
if (emailValue === "") {
emailErr.textContent = "이메일을 입력해주세요.";
emailInput.classList.add("error-input");
emailInput.classList.remove("correct-input");
} else if (!emailValidation(emailValue)) {
emailErr.textContent = "잘못된 이메일 형식입니다.";
emailInput.classList.add("error-input");
emailInput.classList.remove("correct-input");
} else {
emailErr.textContent = "";
emailInput.classList.remove("error-input");
emailInput.classList.add("correct-input");
}
toggleButton();
}

// 비밀번호 검증
function validatePassword() {
const passwordValue = passwordInput.value.trim();
if (passwordValue === "") {
passwordErr.textContent = "비밀번호를 입력해주세요.";
passwordInput.classList.add("error-input");
passwordInput.classList.remove("correct-input");
} else if (passwordValue.length < 8) {
passwordErr.textContent = "비밀번호를 8자 이상 입력해주세요.";
passwordInput.classList.add("error-input");
passwordInput.classList.remove("correct-input");
} else {
passwordErr.textContent = "";
passwordInput.classList.remove("error-input");
passwordInput.classList.add("correct-input");
}
toggleButton();
}

// 비밀번호 보이기/숨기기 기능
function togglePasswordVisibility(input, button) {
if (input.type === "password") {
input.type = "text";
button.innerHTML = '<img src="/images/eye-icon.png" class="eye-icon" alt="eye-off">';
} else {
input.type = "password";
button.innerHTML = '<img src="/images/invisible-eye-icon.png" class="eye-icon" alt="eye-on">';
}
}

// 이벤트 리스너 추가
emailInput.addEventListener("focusout", validateEmail);
passwordInput.addEventListener("focusout", validatePassword);
passwordVisibility.addEventListener("click", () => togglePasswordVisibility(passwordInput, passwordVisibility));

// 엔터 키 입력 시 검증 함수 실행
emailInput.addEventListener("keydown", function(event) {
if (event.key === "Enter") {
validateEmail();
}
});

passwordInput.addEventListener("keydown", function(event) {
if (event.key === "Enter") {
validatePassword();
}
});
133 changes: 133 additions & 0 deletions sign-up.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* login, signup 공통 */

// 이메일 유효성 검사 함수
function emailValidation(email) {
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return emailRegex.test(email);
}

// 요소 가져오기
const emailInput = document.getElementById("email");
const passwordInput = document.getElementById("password");
const passwordRepeatInput = document.getElementById("password-repeat");
const emailErr = document.getElementById("emailErr");
const passwordErr = document.getElementById("passwordErr");
const passwordCheckErr = document.getElementById("passwordCheckErr");
const passwordVisibility = document.getElementById("passwordVisibility");

let isPasswordCheckTouched = false; // 비밀번호 확인 입력 여부 추적

// 초기 오류 메시지 숨김
emailErr.style.display = "none";
passwordErr.style.display = "none";
passwordCheckErr.style.display = "none";

// 이메일 검증
function validateEmail() {
const emailValue = emailInput.value.trim();
if (emailValue === "") {
emailErr.textContent = "이메일을 입력해주세요.";
emailErr.style.display = "block";
emailInput.classList.add("error-input");
emailInput.classList.remove("correct-input");
} else if (!emailValidation(emailValue)) {
emailErr.textContent = "잘못된 이메일 형식입니다.";
emailErr.style.display = "block";
emailInput.classList.add("error-input");
emailInput.classList.remove("correct-input");
} else {
emailErr.style.display = "none";
emailInput.classList.remove("error-input");
emailInput.classList.add("correct-input");
}
toggleButton();
}

// 비밀번호 검증
function validatePassword() {
const passwordValue = passwordInput.value.trim();
if (passwordValue === "") {
passwordErr.textContent = "비밀번호를 입력해주세요.";
passwordErr.style.display = "block";
passwordInput.classList.add("error-input");
passwordInput.classList.remove("correct-input");
} else if (passwordValue.length < 8) {
passwordErr.textContent = "비밀번호를 8자 이상 입력해주세요.";
passwordErr.style.display = "block";
passwordInput.classList.add("error-input");
passwordInput.classList.remove("correct-input");
} else {
passwordErr.style.display = "none";
passwordInput.classList.remove("error-input");
passwordInput.classList.add("correct-input");
}
toggleButton();
}

// 비밀번호 확인 검증
function validatePasswordCheck() {
const passwordValue = passwordInput.value.trim();
const passwordCheckValue = passwordRepeatInput.value.trim();

if (!isPasswordCheckTouched) {
passwordCheckErr.style.display = "none"; // 입력 전에는 오류 문구 숨김
return;
}

if (passwordCheckValue === "") {
passwordCheckErr.style.display = "none"; // 비밀번호 확인 필드가 비었을 때도 오류 메시지 숨김
} else if (passwordValue !== passwordCheckValue) {
passwordCheckErr.textContent = "비밀번호가 일치하지 않습니다.";
passwordCheckErr.style.display = "block";
passwordRepeatInput.classList.add("error-input");
} else {
passwordCheckErr.style.display = "none";
passwordRepeatInput.classList.remove("error-input");
}
toggleButton();
}

// 비밀번호 보이기/숨기기 기능
function togglePasswordVisibility(input, button) {
if (input.type === "password") {
input.type = "text";
button.innerHTML = '<img src="/images/eye-icon.png" class="eye-icon" alt="eye-off">';
} else {
input.type = "password";
button.innerHTML = '<img src="/images/invisible-eye-icon.png" class="eye-icon" alt="eye-on">';
}
}

// 회원가입 버튼 활성화
function toggleButton() {
const isFormValid =
emailErr.style.display === "none" &&
passwordErr.style.display === "none" &&
passwordCheckErr.style.display === "none" &&
emailInput.value.trim() !== "" &&
passwordInput.value.trim() !== "" &&
passwordRepeatInput.value.trim() !== "";

const signupButton = document.querySelector(".signup");
if (isFormValid) {
signupButton.disabled = false;
signupButton.classList.add("active");
} else {
signupButton.disabled = true;
signupButton.classList.remove("active");
}
Comment on lines +111 to +118
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
위의 조건같은 경우 아래처럼 작성하셔도 됩니다.

    const signupButton = document.querySelector(".signup");

    signupButton.disabled = !isFormValid;
    signupButton.classList.toggle("active", isFormValid);

}

// 이벤트 리스너 추가
emailInput.addEventListener("focusout", validateEmail);
passwordInput.addEventListener("focusout", validatePassword);
passwordRepeatInput.addEventListener("input", () => {
isPasswordCheckTouched = true; // 사용자가 입력 시작했음을 추적
validatePasswordCheck(); // 입력 시에도 검증 함수 실행
});
passwordRepeatInput.addEventListener("keydown", function(event) {
if (event.key === "Enter") {
validatePasswordCheck();
}
});
passwordVisibility.addEventListener("click", () => togglePasswordVisibility(passwordInput, passwordVisibility));
22 changes: 14 additions & 8 deletions signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,33 @@ <h1>판다마켓</h1>
<form>
<div class="group">
<label for="email">이메일</label>
<input type="email" id="email" name="email">
<input type="email" id="email" name="email" placeholder="이메일을 입력해주세요."
class="error-input">
<p id="emailErr" class="errMsg">이메일을 입력해주세요.</p>
</div>
<div class="group">
<label for="username">닉네임</label>
<input type="username" id="username" name="username">
<input type="username" id="username" name="username" placeholder="닉네임을 입력해주세요.">
<p id="nicknameErr" class="errMsg"></p>
</div>
<div class="group">
<label for="password">비밀번호</label>
<div class="password-input">
<input type="password" id="password" name="password">
<input type="password" id="password" name="password" placeholder="비밀번호를 입력해주세요.">
<img src="./image/invisible_icon.png" class="password-icon" alt="비밀번호 보기">
<p id="passwordErr" class="errMsg">비밀번호를 8자 이상 입력해주세요.</p>
</div>
</div>
<div class="group">
<label for="password-repeat">비밀번호 확인</label>
<div class="password-input">
<input id="password-repeat" name="password-repeat">
<img src="./image/eye_icon.png" class="password-icon" alt="비밀번호 보기">
<input id="password-repeat" name="password-repeat" placeholder="비밀번호를 다시 한 번 입력해주세요."
class="error-input">
<img src="./image/eye_icon.png" class="password-icon1" alt="비밀번호 보기">
<p id="passwordCheckErr" class="errMsg">비밀번호가 일치하지 않습니다.</p>
</div>
</div>
<button type="submit">로그인</button>
<button type="submit">회원가입</button>
</form>
</div>
<div class="bottom">
Expand All @@ -61,12 +67,12 @@ <h1>간편 로그인하기</h1>
</div>
</div>
<div class="footer">
<h1>판다마켓이 처음이신가요?</h1>
<p>이미 회원이신가요?</p>
<a href="./sign-in.html">로그인</a>
</div>


</div>

<script src='./sign-up.js'></script>
</body>
</html>
Loading
Loading