JS_검색, 장바구니, 영수증 모달 구현 정리

jjyu_my·2025년 3월 2일
0

JAVASCRIPT

목록 보기
14/14
post-thumbnail

👩🏻‍💻 테스트 삼아 진행한 미니 프로젝트, 진행하면서 어려웠던 부분을 정리해봤다!


🔎 검색바 & 검색한 내용에 배경 컬러 입히기

  • 검색바 구현인데 검색한 상품만 나오게 구현하였다
  • 단! 기존 방식과 다르게, 검색한 내용에 배경색을 추가해보았다

📌 HTML

<!-- 상품 검색 -->
<div>
  <input type="text" id="search" placeholder="검색어 입력" />
  <button id="searchBtn">검색</button>
</div>

📌 Javascript

  • 검색기능까지는 손쉽게 구현하였지만 배경컬러 입히는 부분에서 살짝 시간을 잡아먹었다.
  • 찾아보니 정규표현식을 이용한 검색어 하이라이트 적용방법이 있어서 이 방법을 적용하였다
// 검색 기능
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 : 정규표현식에서 첫 번째 그룹(검색어 부분) 을 의미

🔍 결과 : 검색한 상품 제목에 하이라이트 배경색이 적용


📦 상품을 장바구니에 담기 (드래그 앤 드롭 + 버튼 클릭)

📌 HTML

<!-- 상품 리스트 -->
<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>

📌 Javascript

  • 제일 오래 걸린 부분이었다.. 😅 드래그하여 상품을 끌어오기는 처음 접해보았다... 배울 게 아직 많구나? 🤔
/**
 * ✅ 드래그 앤 드롭 으로 장바구니에 상품 추가
 * ✅ 상품 담기 버튼 클릭 시 장바구니에 상품 추가
 * ✅ 장바구니에 추가된 상품 수량 보이기
 */

// 장바구니 컨테이터 선택
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}`;
}

🔍 결과 : 상품을 드래그하거나 담기 버튼을 클릭하면 장바구니에 추가되고, 가격이 자동으로 업데이트

  • 상품 수량 부분에 커서를 놓고 delete key 를 누르면 상품이 삭제됨! ❌

🧾 영수증 모달 만들기

  • canvas 태그를 처음 알았다...ㅎㅎ 부끄럽다아..ㅎㅎㅎ
  • canvas 태그를 사용하여 간단하게 영수증 을 만들어보았다ㅎㅎ

📌 HTML

<!-- 구매하기 모달 -->
<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>

📌 Javascript

// 영수증 그리기
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);
}

🔍 결과 : 사용자가 입력한 성함과 연락처가 포함된 영수증을 캔버스에 그려서 출력할 수 있다


profile

0개의 댓글

관련 채용 정보