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
File renamed without changes.
132 changes: 74 additions & 58 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,71 +1,87 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="style.css" rel="stylesheet">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link href="style.css" rel="stylesheet" />
<title>판다마켓</title>
</head>
<body>
<header class="one">
<div class="two">
<p class="three"> <img src="images/favicon.ico" class="four"><span class="five">판다마켓</span></p>
<button class="six"><a href="login/login.html">로그인</a></button>
<header class="header-container">
<div class="header-content">
<p class="logo-wrapper">
<img src="images/favicon.ico" class="logo-icon" alt="Panda Market Logo" />
<span class="logo-text">판다마켓</span>
</p>
<a href="login/login.html" class="login-button">로그인</a>
</div>
</header>
<div class="seven">
<div class="eight">
<div class="nine">
<span class="ten">일상의 모든 물건을<br>
거래해 보세요</span>
<button class="first"><a href="items.html">구경하러 가기</a></button>

<main class="hero-wrapper">
<section class="hero-section">
<div class="hero-content">
<span class="hero-text">일상의 모든 물건을<br />거래해 보세요</span>
<a href="items.html" class="main-cta-button">구경하러 가기</a>
</div>
<img src="images/jj.png" class="hero-image" alt="Main Promotion Image" />
</section>
</main>

<section class="feature-section">
<div class="feature-content">
<img src="images/feature1-image.png" class="feature-image" alt="Hot Item Image" />
<div class="feature-textbox">
<p class="feature-title">Hotitem</p>
<p class="feature-heading">인기 상품을 확인해 보세요</p>
<p class="feature-desc">가장 HOT한 중고거래 물품을 판다 마켓에서 확인해 보세요</p>
</div>
<img src="images/jj.png" class="second">
</div>
</div>
<div class="big">
<div class="special">
<img src="images/feature1-image.png" class="thrid">
<div class="fourth">
<p class="fifth">Hotitem</p>
<p class="sixth">인기 상품을 확인해 보세요</p>
<p class="seventh">가장 HOT한 중고거래 물품을
판다 마켓에서 확인해 보세요</p>
</div>
</div>
<div class="big">
<div class="special">
<div class="fourth">
<p class="fifth">search</p>
<p class="sixth">구매를 원하는 상품을 검색하세요</p>
<p class="seventh">구매하고 싶은 물품은 검색해서 쉽게 찾아보세요
</p>
</div>
<img src="images/feature2-image.png" class="thrid">
</div>
<div class="big">
<div class="special">
<img src="images/feature3-image.png" class="thrid">
<div class="fourth">
<p class="fifth">regular</p>
<p class="sixth">판매를 원하는 상품을 등록하세요</p>
<p class="seventh">어떤 물건이든 판매하고 싶은 상품을 쉽게 등록하세요</p>
</div>
</div>
<div class="eighth">
<div class="ninth">
<p class="tenth">믿을 수 있는<br>
판다마켓 중고 거래</p>
<img src="images/bottom-banner-image.png" class="last">
</section>

<section class="feature-section">
<div class="feature-content">
<div class="feature-textbox">
<p class="feature-title">search</p>
<p class="feature-heading">구매를 원하는 상품을 검색하세요</p>
<p class="feature-desc">구매하고 싶은 물품은 검색해서 쉽게 찾아보세요</p>
</div>
<img src="images/feature2-image.png" class="feature-image" alt="Search Item Image" />
</div>
</div>
<div class="lastone">
<div class="lasttwo">
<p class="word">codeit-2024</p>
<p class="wordtwo"><a href="privacy.html">privacy policy</a><a href="faq.html"> FAQ</a></p>
<div><a href="https://www.facebook.com/"><img src="images/facebook-logo.svg"></a><a href="https://www.twitter.com"><img src="images/twitter-logo.svg"></a><a href="https://www.youtube.com"><img src="images/youtube-logo.svg"></a><a href="https://www.instagram.com"><img src="images/instagram-logo.svg"></a></div>
</section>

<section class="feature-section">
<div class="feature-content">
<img src="images/feature3-image.png" class="feature-image" alt="Register Item Image" />
<div class="feature-textbox">
<p class="feature-title">regular</p>
<p class="feature-heading">판매를 원하는 상품을 등록하세요</p>
<p class="feature-desc">어떤 물건이든 판매하고 싶은 상품을 쉽게 등록하세요</p>
</div>
</div>
</section>

<section class="trust-section">
<div class="trust-content">
<p class="trust-text">믿을 수 있는<br />판다마켓 중고 거래</p>
<img src="images/bottom-banner-image.png" class="trust-image" alt="Trust Banner Image" />
</div>
</section>

<footer class="footer">
<div class="footer-content">
<p class="footer-text">codeit-2024</p>
<p class="footer-links">
<a href="privacy.html">privacy policy</a>
<a href="faq.html"> FAQ</a>
</p>
<div class="footer-sns">
<a href="https://www.facebook.com/"><img src="images/facebook-logo.svg" alt="Facebook Logo" /></a>
<a href="https://www.twitter.com"><img src="images/twitter-logo.svg" alt="Twitter Logo" /></a>
<a href="https://www.youtube.com"><img src="images/youtube-logo.svg" alt="YouTube Logo" /></a>
<a href="https://www.instagram.com"><img src="images/instagram-logo.svg" alt="Instagram Logo" /></a>
</div>
</div>
</div>
</footer>
</body>
</html>
</html>
File renamed without changes.
79 changes: 61 additions & 18 deletions login/login.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,67 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="style.css">
<title>로그인</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="style.css" />
<title>로그인</title>
</head>
<body>
<div class="one">
<h1 class="two"><a href="../index.html"><img class="three" src="../images/panda-market-logo.png"></a></h1>
<form class="four">
<label for="email" class="five">이메일</label>
<input class="six" id="email" name="username" type="email" placeholder="[email protected]" required automoplete="on">
<label for="password"class="five">비밀번호</label>
<input class="six" id="password" name="password" type="password" required automoplete="on">
</form>
<button class="seven">로그인</button>
<div class="eight"><div class="nine"><h1 class="ten">간편 로그인하기</h1><div class="eleven"><a href="https://www.google.com/"><img src="../images/google.png"></a><a href="https://www.kakaocorp.com/page/"><img src="../images/kakao.png"></a></div></div></div>
<h1 class="last">판다마켓이 처음이신가요?<a href="../signup/signup.html">회원가입</a></h1>
</div>
<main class="login-container">
Copy link
Collaborator

Choose a reason for hiding this comment

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

classname 이 직관적이고 일관성 있게 수정되었네요👍👍

<h1 class="logo-title">
<a href="../index.html">
<img class="logo-image" src="../images/panda-market-logo.png" alt="판다마켓 로고" />
</a>
</h1>

<form class="login-form">
Copy link
Collaborator

Choose a reason for hiding this comment

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

Form 구현을 위한 시맨틱 태그 (form, input, label 등)을 아주 잘 활용해주셨습니다.👍 특히 label 의 for 속성까지 꼼꼼히 추가해주신 점 좋습니다!

<label for="email" class="form-label">이메일</label>
<input
class="form-input"
id="email"
name="username"
type="email"
placeholder="[email protected]"
required
autocomplete="on"
/>
<p id="email-error"></p>

<label for="password" class="form-label">비밀번호</label>
<input
class="form-input"
id="password"
name="password"
type="password"
required
autocomplete="on"
/>
<p id="password-error"></p>
</form>

<button class="login-button" type="button" disabled>로그인</button>
Copy link
Collaborator

Choose a reason for hiding this comment

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

form 태그 내부에서 input 과 button 을 연결하기 위해서는 type=submit 을 지정해주셔야 합니다.


<section class="social-login-section">
<div class="social-login-box">
<h1 class="social-login-title">간편 로그인하기</h1>
<div class="social-icons">
<a href="https://www.google.com/">
<img src="../images/google.png" alt="Google 로그인" />
</a>
<a href="https://www.kakaocorp.com/page/">
<img src="../images/kakao.png" alt="Kakao 로그인" />
</a>
</div>
</div>
</section>

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

<script src="login.js"></script>
</body>
</html>
</html>
47 changes: 47 additions & 0 deletions login/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
document.addEventListener('DOMContentLoaded', function () {
const email = document.querySelector('#email');
const error = document.querySelector('#email-error');
const password = document.querySelector('#password');
const pwerror = document.querySelector('#password-error');
const button = document.querySelector('.login-button');

button.disabled = true;

email.addEventListener('focusout', function (e) {
const value = e.target.value;
if (value === '') {
error.textContent = '이메일을 입력해주세요';
} else if (!value.includes('@') || !value.includes('.')) {
error.textContent = '잘못된 이메일 형식입니다';
} else {
error.textContent = '';
}
checkValid();
});

password.addEventListener('focusout', function (e) {
const value = e.target.value;
if (value === '') {
pwerror.textContent = '비밀번호를 입력해주세요';
} else if (value.length < 8) {
pwerror.textContent = '비밀번호를 8자 이상 입력해주세요';
} else {
pwerror.textContent = '';
}
checkValid();
});

button.addEventListener('click', function () {
if (!button.disabled) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

버튼이 disabled 상태면 애초에 클릭 이벤트가 발생하지 않기 때문에, 이 조건은 사실상 불필요합니다.

또한, 단순히 클릭 이벤트핸들러만 등록하게 되면 엔터키 입력 이벤트에 대한 유효성 검사를 놓칠 수 있습니다.

따라서 form 요소의 유효성 검사를 위한 이벤트핸들러를 등록할 때에는 'submit' 이벤트를 활용해주시는게 좋습니다. 단 submit 을 활요하기 위해서는 제출 버튼에 <button type="submit"> 을 설정해주셔야 합니다.

Copy link
Collaborator

Choose a reason for hiding this comment

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

추가로, checkValid() 함수에서 버튼의 활성화 여부를 이미 판단하고 있음에도 불구하고, click 이벤트 안에서 다시 button.disabled 상태를 조건으로 사용하는 것은 중복된 검증이며, 코드 흐름을 명확하게 하지 못하는 방식입니다.

disabled와 같은 UI 상태는 “결과값”으로서 존재해야지, 다른 동작의 “의사결정 기준”으로 사용되면 의존성이 잘못된 방향으로 흘러갈 수 있습니다.

즉, 로직의 핵심 판단이 DOM 상태에 의존하게 되면, 상태 관리와 사이드이펙트의 경계가 흐려져 유지보수성이 떨어질 수 있으니 이런 방식은 지양해주시는게 좋습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

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

결론적으로 아래와 같은 방식으로 수정되면 좋을 것 같네요!

const form = document.querySelector('#login-form');
form.addEventListener('submit', (e) => {
  e.preventDefault();
  const isValid = checkValid()
  if(isValid) {
  location.href = '../items/items.html';
}
});

location.href = '../items/items.html';
}
});

function checkValid() {
const emailValue = email.value;
const passwordValue = password.value;
const isEmailValid = emailValue.includes('@') && emailValue.includes('.');
const isPasswordValid = passwordValue.length >= 8;
button.disabled = !(isEmailValid && isPasswordValid);
}
});
Loading
Loading