👩🏻💻 테스트 삼아 진행한 미니 프로젝트, 진행하면서 어려웠던 부분을 정리해봤다!
<!-- 상품 검색 -->
<div>
<input type="text" id="search" placeholder="검색어 입력" />
<button id="searchBtn">검색</button>
</div>
// 검색 기능
function searchProducts() {
const searchText = document.querySelector("#search").value.toLowerCase().trim();
const filteredProducts = allProducts.filter((item) => item.title.toLowerCase().includes(searchText));
productList(filteredProducts); // 검색된 상품 리스트 보여주기
// 검색된 텍스트에 배경 컬러 입히기
if (searchText) {
const productTitles = document.querySelectorAll(".card-title");
productTitles.forEach((title) => {
const originalText = title.textContent;
const regex = new RegExp(`(${searchText})`, "gi");
title.innerHTML = originalText.replace(regex, `<span style="background-color: yellow;">$1</span>`);
});
}
}
💡 정규표현식을 이용한 검색어 하이라이트 적용_코드설명
1️⃣ new RegExp(\(${searchText})`, "gi")
- 사용자가 입력한 searchText 를 포함하는 동적 정규표현식을 생성
- (${searchText}) : 검색어 부분을 그룹화 (괄호로 감싼 부분이 $1 로 참조됨)
- "g" : 전체 텍스트에서 모든 검색어 찾기 (전역 검색)
- "i" : 대소문자 구분 없이 찾기
2️⃣ originalText.replace(regex, \<span style="background-color: yellow;">$1</span>`)
- originalText(상품 제목)에서 정규표현식(regex)에 매칭되는 부분을 <span> 태그로 감싸 배경 색을 입힘
$1 : 정규표현식에서 첫 번째 그룹(검색어 부분) 을 의미
<!-- 상품 리스트 -->
<div id="product-list" class="product-list product"></div>
<!-- 장바구니 -->
<div class="cart-container">
<div class="carttext">장바구니(드래그 가능)</div>
<div id="cart1" class="cart" ondrop="drop(event)" ondragover="allowDrop(event)">
<p>여기로 드래그 해주세요</p>
</div>
<div class="total">
<p>최종가격</p>
<div class="totalprice">합계 : 0</div>
<button class="totalBtn">구매하기</button>
</div>
</div>
/**
* ✅ 드래그 앤 드롭 으로 장바구니에 상품 추가
* ✅ 상품 담기 버튼 클릭 시 장바구니에 상품 추가
* ✅ 장바구니에 추가된 상품 수량 보이기
*/
// 장바구니 컨테이터 선택
const cartContainer = document.querySelector("#cart1");
let cartItems = {}; // 장바구니에 담긴 상품들을 저장할 객체
// 📌 상품 드래그 앤 드롭 관련 함수
function allowDrop(event) {
event.preventDefault(); // 드롭 이벤트 허용
}
function drag(event) {
// 드래그한 상품의 이름을 데이터로 저장
event.dataTransfer.setData(
"text",
event.target.querySelector(".card-title").textContent
);
}
function drop(event) {
event.preventDefault(); // 드롭 이벤트 허용
const productName = event.dataTransfer.getData("text"); // 드래그한 상품 이름 가져오기
addToCart(productName); // 장바구니에 상품 추가
}
// 📌 담기 버튼 클릭 시 상품 추가
const productContainer = document.querySelector("#product-list"); // 상품 목록 컨테이너 선택
productContainer.addEventListener("click", function (event) {
if (event.target.classList.contains("btn-primary")) {
const productName = event.target
.closest(".card")
.querySelector(".card-title").textContent;
addToCart(productName);
}
});
// 📌 장바구니에 상품 추가하는 함수
function addToCart(productName) {
// 상품 이름을 받아와서 장바구니에 추가
const product = allProducts.find((item) => item.title === productName); // 상품 목록에서 상품 찾기
if (!product) return; // 상품이 없으면 함수 종료
// 이미 장바구니에 담긴 상품이면 수량만 증가
if (cartItems[productName]) {
cartItems[productName].quantity += 1;
} else {
// 장바구니에 없는 상품이면 수량을 1로 해서 추가
cartItems[productName] = { ...product, quantity: 1 };
}
updateCartUI(); // 장바구니 UI 업데이트
}
// 📌 장바구니 UI 업데이트 + 합계 가격 업데이트
function updateCartUI() {
cartContainer.innerHTML = ""; // 기존 장바구니 내용 비우기
let totalPrice = 0; // 총 가격을 저장할 변수
Object.values(cartItems).forEach((item) => {
const cartCard = document.createElement("div");
cartCard.classList.add("cart-card");
cartCard.innerHTML = `
<div class="card" style="width: 18rem; padding: 20px; margin: 10px;">
<img src="../img/${item.photo}" class="card-img-top">
<div class="card-body">
<h5 class="card-title">${item.title}</h5>
<p class="card-text">${item.brand}</p>
<p class="card-text">${item.price}원</p>
<input type="number" class="cart-quantity" value="${item.quantity}" min="1" data-title="${item.title}">
</div>
</div>ㅎ
`;
cartContainer.appendChild(cartCard);
// 📌 상품 가격 * 수량을 누적하여 총 가격 계산
totalPrice += item.price * item.quantity;
});
// 📌 총 가격 업데이트
document.querySelector(".totalprice").innerText = `합계 : ${totalPrice}원`;
}
<!-- 구매하기 모달 -->
<div class="modal1">
<div class="white-bg">
<form>
<div class="my-3">성함 <input type="text" class="form-control" id="name" placeholder="성함을 입력하세요" /></div>
<div class="my-3">연락처 <input type="tel" class="form-control" id="phone" placeholder="연락처를 입력하세요" /></div>
<button type="submit" class="btn btn-primary">입력완료</button>
<button type="button" class="btn btn-danger" id="close">닫기</button>
</form>
</div>
</div>
<!-- 영수증 모달 -->
<div class="modal2">
<div class="white-bg">
<h4>영수증</h4>
<canvas id="canvas" width="350" height="350"></canvas>
<div><button id="close">닫기</button></div>
</div>
</div>
// 영수증 그리기
function drawReceipt(name, phone) {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height); // 캔버스 초기화
ctx.fillStyle = "#f0f0f0";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#000";
ctx.font = "20px Arial";
ctx.textAlign = "left";
const currentDate = new Date().toLocaleString();
ctx.fillText(`날짜: ${currentDate}`, 20, 30);
ctx.fillText(`성함: ${name}`, 20, 60);
ctx.fillText(`연락처: ${phone}`, 20, 90);
}