-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
7 changed files
with
208 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
.search-container { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
max-width: 500px; | ||
margin: 0 auto; | ||
} | ||
|
||
.search-input { | ||
width: 70%; | ||
height: 58px; | ||
padding: 10px; | ||
border: 1px solid #dddddd; | ||
border-radius: 3px; | ||
font-size: 1.5em; | ||
} | ||
|
||
.search-button { | ||
width: 15%; | ||
text-align: center; | ||
border-radius: 3px; | ||
background: #2ac1bc; | ||
font-size: 20px; | ||
color: white; | ||
} | ||
|
||
|
||
|
||
select { | ||
background-color: white; | ||
border: thin solid; | ||
border-radius: 4px; | ||
display: inline-block; | ||
font: inherit; | ||
line-height: 1.5em; | ||
padding: 0.5em 3.5em 0.5em 1em; | ||
|
||
margin: 0; | ||
box-sizing: border-box; | ||
-webkit-appearance: none; | ||
-moz-appearance: none; | ||
background-image: | ||
linear-gradient(45deg, transparent 50%, gray 50%), | ||
linear-gradient(135deg, gray 50%, transparent 50%), | ||
linear-gradient(to right, #ccc, #ccc); | ||
background-position: | ||
calc(100% - 20px) calc(1em + 2px), | ||
calc(100% - 15px) calc(1em + 2px), | ||
calc(100% - 2.5em) 0.5em; | ||
background-size: | ||
5px 5px, | ||
5px 5px, | ||
1px 1.5em; | ||
background-repeat: no-repeat; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,24 @@ | ||
const search = () => { | ||
const keyword = document.getElementById("keyword").value.trim(); | ||
const form = document.getElementById('search-form'); | ||
|
||
if (keyword === "") { | ||
alert("검색어를 입력해주세요."); | ||
return; | ||
} | ||
form.addEventListener('submit', (event) => { | ||
event.preventDefault(); | ||
|
||
window.location.href = '/search?keyword='.concat(keyword).concat("&sort=id,desc"); | ||
} | ||
const searchInput = document.getElementById("searchInput").value; | ||
const sortSelect = document.getElementById("sortSelect"); | ||
const selectedSort = sortSelect.options[sortSelect.selectedIndex].value; | ||
let queryParams = `keyword=${searchInput}&sort=${selectedSort}`; | ||
|
||
const selectSortKey = (sortKey) => { | ||
const buttons = document.getElementsByName("sort-select-button"); | ||
let button; | ||
if (sortKey === "id,desc") { | ||
button = buttons[0]; | ||
} else if(sortKey === "price,desc") { | ||
button = buttons[1]; | ||
} else if(sortKey === "price,asc") { | ||
button = buttons[2]; | ||
} else if(sortKey === "orderCount,desc") { | ||
button = buttons[3]; | ||
} else if (sortKey === "rate,desc") { | ||
button = buttons[4]; | ||
} else { | ||
console.error("Invalid Sort: ".concat(sortKey)); | ||
return; | ||
if (selectedSort === "orderCount,desc" || selectedSort === "rate,desc") { | ||
const gender = document.getElementById("gender").value; | ||
const birthYearRange = document.getElementById("birthYearRange").value; | ||
if (gender && birthYearRange) { | ||
queryParams += `&gender=${gender}&birthYearRange=${birthYearRange}`; | ||
} | ||
else if (gender || birthYearRange) { | ||
alert("성별과 나이대 모두 선택해주세요."); | ||
} | ||
} | ||
|
||
button.style.fontWeight = "bold"; | ||
button.style.color = "white"; | ||
button.style.backgroundColor = "darkslategray"; | ||
} | ||
window.location.href = `/search?${queryParams}`; | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> | ||
<head> | ||
<meta charset="UTF-8"/> | ||
<meta content="IE=edge" http-equiv="X-UA-Compatible"/> | ||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> | ||
<link rel="stylesheet" th:href="@{/css/index.css}"> | ||
<title>Shopping</title> | ||
</head> | ||
<body> | ||
<section class="search-container" th:fragment="searchbar"> | ||
<form class="full-width mt-30" id="search-form"> | ||
<div class="full-width flex justify-center"> | ||
<label for="searchInput"></label> | ||
<input class="search-input" id="searchInput" placeholder="검색어를 입력하세요" required type="text"> | ||
<button class="search-button" id="searchButton" type="submit">검색</button> | ||
</div> | ||
|
||
<div class="mt-30 flex justify-around"> | ||
<div> | ||
<label for="sortSelect">정렬</label> | ||
<div class="select"> | ||
<select id="sortSelect"> | ||
<option selected value="id,desc">최신순</option> | ||
<option value="price,desc">가격 높은순</option> | ||
<option value="price,asc">가격 낮은순</option> | ||
<option value="orderCount,desc">주문 많은순</option> | ||
<option value="rate,desc">별점 높은순</option> | ||
</select> | ||
</div> | ||
</div> | ||
|
||
<div> | ||
<label for="gender">성별</label> | ||
<div class="select"> | ||
<select id="gender" name="gender"> | ||
<option selected></option> | ||
<option value="MALE">남자</option> | ||
<option value="FEMALE">여자</option> | ||
</select> | ||
</div> | ||
</div> | ||
|
||
<div> | ||
<label for="birthYearRange">나이대</label> | ||
<div class="select"> | ||
<select id="birthYearRange" name="birthYearRange"> | ||
<option selected></option> | ||
<option value="UNDER_TEENS">10대 이하</option> | ||
<option value="EARLY_TWENTIES">20대 초반</option> | ||
<option value="MID_TWENTIES">20대 중반</option> | ||
<option value="LATE_TWENTIES">20대 후반</option> | ||
<option value="THIRTIES">30대</option> | ||
<option value="OVER_FORTIES">40대 이상</option> | ||
</select> | ||
</div> | ||
</div> | ||
|
||
</div> | ||
</form> | ||
<script> | ||
document.addEventListener("DOMContentLoaded", function () { | ||
const urlParams = new URLSearchParams(window.location.search); | ||
if (urlParams.size === 0) { | ||
return; | ||
} | ||
|
||
document.getElementById("searchInput").value = urlParams.get("keyword"); | ||
document.getElementById("sortSelect").value = urlParams.get("sort"); | ||
document.getElementById("gender").value = urlParams.get("gender"); | ||
document.getElementById("birthYearRange").value = urlParams.get("birthYearRange"); | ||
|
||
fetch('/api/v1/products/search?' + urlParams, { | ||
method: 'GET', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}).then((response) => { | ||
return response.json(); | ||
}).then((data) => { | ||
const currentPage = data.currentPage; | ||
const totalPage = data.totalPage; | ||
const size = data.size; | ||
|
||
let element = ''; | ||
for (let i = 0; i < Math.min(size, data.contents.length); i++) { | ||
let product = data.contents[i]; | ||
element += ` | ||
<div class="product-item"> | ||
<a href="/product/${product.id}"> | ||
<img class="w-280 h-280 cover-image" src="assets/${product.imageFileName}"/> | ||
</a> | ||
<div class="flex justify-between w-280 p-5"> | ||
<div class="product-info"> | ||
<span class="product-info__name">${product.name}</span> | ||
<span class="product-info__price">${product.price}</span> | ||
</div> | ||
<button type="submit" class="product-btn" ${product.stock <= 0 ? 'disabled' : ''} onclick="addCartItem(${product.id})"> | ||
<img src="assets/svgs/cart.svg" alt="장바구니"/> | ||
</button> | ||
</div> | ||
</div> | ||
`; | ||
} | ||
|
||
pagination(currentPage, totalPage, size, '.pagination', urlParams); | ||
document.querySelector('.product-container').innerHTML = element; | ||
}).catch((error) => { | ||
console.error(error); | ||
}); | ||
}); | ||
</script> | ||
<script th:src="@{/js/pagination.js}"></script> | ||
<script th:src="@{/js/cart.js}"></script> | ||
<script th:src="@{/js/search.js}"></script> | ||
</section> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,20 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html"> | ||
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns:th="http://www.thymeleaf.org"> | ||
<head> | ||
<meta charset="UTF-8"/> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||
<meta content="IE=edge" http-equiv="X-UA-Compatible"/> | ||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> | ||
<link rel="stylesheet" th:href="@{/css/index.css}"> | ||
<title>Shopping</title> | ||
</head> | ||
<body> | ||
<div class="root"> | ||
<div th:replace="~{layouts/header :: header}"></div> | ||
<label class="product-search-container"> | ||
<input th:type="text" placeholder="상품을 검색하세요" id="keyword"> | ||
<input th:type="submit" value="검색" onclick="search()"> | ||
</label> | ||
<div class="product-search-result"> | ||
<span th:text="${param.keyword}" style="font-weight: bold; color: darkslategray"></span> | ||
에 대한 검색 결과입니다 | ||
</div> | ||
<div class="product-sort-container"> | ||
<button type="button" | ||
th:onclick="|location.href='@{/search(keyword=${param.keyword}, sort=${value})}'|" | ||
th:with="value='id,desc'" | ||
name="sort-select-button">최신순</button> | ||
<button type="button" | ||
th:onclick="|location.href='@{/search(keyword=${param.keyword}, sort=${value})}'|" | ||
th:with="value='price,desc'" | ||
name="sort-select-button">가격 높은순</button> | ||
<button type="button" | ||
th:onclick="|location.href='@{/search(keyword=${param.keyword}, sort=${value})}'|" | ||
th:with="value='price,asc'" | ||
name="sort-select-button">가격 낮은순</button> | ||
<button type="button" | ||
th:onclick="|location.href='@{/search(keyword=${param.keyword}, sort=${value})}'|" | ||
th:with="value='orderCount,desc'" | ||
name="sort-select-button">주문 많은순</button> | ||
<button type="button" | ||
th:onclick="|location.href='@{/search(keyword=${param.keyword}, sort=${value})}'|" | ||
th:with="value='rate,desc'" | ||
name="sort-select-button">별점 높은순</button> | ||
</div> | ||
<div th:replace="~{layouts/searchbar :: searchbar}"></div> | ||
|
||
<section class="product-container"> | ||
<div class="product-list"> | ||
</div> | ||
</section> | ||
<div class="pagination"></div> | ||
</div> | ||
</body> | ||
<script> | ||
document.addEventListener("DOMContentLoaded", function () { | ||
const urlParams = new URLSearchParams(window.location.search); | ||
|
||
fetch('/api/v1/products/search?' + urlParams, { | ||
method: 'GET', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}).then((response) => { | ||
return response.json(); | ||
}).then((data) => { | ||
const currentPage = data.currentPage; | ||
const totalPage = data.totalPage; | ||
const size = data.size; | ||
|
||
let element = ''; | ||
for (let i = 0; i < Math.min(size, data.contents.length); i++) { | ||
let product = data.contents[i]; | ||
element += ` | ||
<div> | ||
<a href="/product/${product.id}"> | ||
<img class="w-280 h-280 cover-image" src="assets/${product.imageFileName}"/> | ||
</a> | ||
<div class="flex justify-between w-280 p-5"> | ||
<div class="product-info"> | ||
<span class="product-info__name">${product.name}</span> | ||
<span class="product-info__price">${product.price}</span> | ||
</div> | ||
<button type="submit" class="product-btn" ${product.stock <= 0 ? 'disabled' : ''} onclick="addCartItem(${product.id})"> | ||
<img src="assets/svgs/cart.svg" alt="장바구니"/> | ||
</button> | ||
</div> | ||
</div> | ||
`; | ||
} | ||
|
||
selectSortKey(urlParams.get("sort")); | ||
pagination(currentPage, totalPage, size, '.pagination', urlParams); | ||
document.querySelector('.product-list').innerHTML = element; | ||
}).catch((error) => { | ||
console.error(error); | ||
}); | ||
}); | ||
</script> | ||
<script th:src="@{/js/pagination.js}"></script> | ||
<script th:src="@{/js/cart.js}"></script> | ||
<script th:src="@{/js/search.js}"></script> | ||
</html> |