작성폼_productSearch.drawio.png

1️⃣[myHomeForm.jsp] - 제품검색 버튼을 누르면 모달창 생성

<!-- 모달창 -->
				<div id="prodSearchModal" class="modal">
				    <div class="modal-header">
				        <strong>🛒 제품 검색</strong>
				        <button type="button" onclick="closeProdSearch()" class="modal-close">&times;</button>
				    </div>
				
				    <div class="modal-body">
				        <input type="text" id="searchKeyword" placeholder="상품명을 입력하세요" class="search-input">
				        <button type="button" id="modalprodSearchBtn" onclick="searchProduct()"> 검색🔍</button>
				        <div id="productResults" class="search-results"></div>
				    </div>
				</div>
				
				<div class="prodHeader">
					<!-- 상품 검색 버튼 -->
					<button type="button" id="prodSearchBtn" onclick="openProdSearch()">제품 검색</button>
	            	<!-- 미리보기 -->
	            	<h3>우리집에 사용된 제품</h3>
	            </div>
	            <div id="prodPreview" class="prodPreview"></div>

ajax로 productController로 데이터 요청 (검색창에 입력하는 keyword 보냄)

document.getElementById("searchKeyword").addEventListener("keydown", function(event) {
    if (event.key === "Enter") {
        event.preventDefault(); // 기본 동작 방지
        searchProduct(); // 검색 함수 실행
    }
});

function openProdSearch() {
  document.getElementById('prodSearchModal').style.display = 'block';
}

function closeProdSearch() {
  document.getElementById('prodSearchModal').style.display = 'none';
}

function searchProduct(){
	const keyword = document.getElementById('searchKeyword').value;
	
	 $.ajax({
	      type: "GET", 
	        url: "/gami/product/productSearch.do", 
	        data: {keyword: keyword},
	        dataType: "json",   
	        success: function(response) {  	
	            const resultDiv = document.getElementById("productResults");
	            resultDiv.innerHTML = "";
	            
	            if (response.products && response.products.length > 0) {
	                const products = response.products;
	                
	                for (let i = 0; i < products.length; i++) {
	                    const product = products[i];

	                    const div = document.createElement("div");
	                    div.className = "prodList";
	                    div.style.cursor = "pointer";
	                    
	                    const img = document.createElement("img");
	                    img.className = "prodImage";
	                    img.src = "/gami/product/productThumbnail.do?articleNO=" + product.productNO + "&image=" + encodeURIComponent(product.imageFileName);
	                    img.alt = product.productName;
	                    img.width = 60;

	                    const nameP = document.createElement("p");
	                    nameP.className = "prod";
	                    nameP.style.marginTop = "5px";
	                    nameP.innerHTML = "<font size=3>" + product.productName + "</font>";

	                    div.appendChild(img);
	                    div.appendChild(nameP);

	                    div.onclick = function () {
	                        prodPreView(product);
	                        closeProdSearch();
	                    };

	                    resultDiv.appendChild(div);
	                }
	            } else {
	                resultDiv.innerText = "검색 결과가 없습니다.";
	            }
	        },

	        error: function(xhr, status, error) {
	            console.log("오류 발생:", error);
	            alert("서버와 통신 중 문제가 생겼습니다.");
	        }
	    });
	}

[productController]

 	@RequestMapping(value = "/productSearch.do", method = RequestMethod.GET)
 	@ResponseBody
 	public Map<String, Object> productSearch(@RequestParam("keyword") String keyword) throws Exception {
 		
 		System.out.println("keyword 어서오시옵소서 : " + keyword);	
 		List<ProductDomain> searchedProdList = productService.productSearching(keyword);
 		System.out.println("리스트 오시옵소서 : "+searchedProdList);
 		
 		Map<String, Object> resultMap = new HashMap<>();		
 		resultMap.put("products", searchedProdList);

 		return resultMap;
 	}

5️⃣[mapper]

 <select id="searchingProd" resultType="ProductDomain" parameterType="String">
        SELECT 
		    p.productNo, 
		    p.productName, 
		    p.productDescription, 
		    p.productPrice,
		    i.imageFilename
		FROM (
		    SELECT productNo, productName, productDescription, productPrice,
		           ROW_NUMBER() OVER (PARTITION BY productName ORDER BY productOptions) AS rn
		    FROM product
		) p
		LEFT JOIN (
		    SELECT articleNo, MIN(imageFilename) AS imageFilename
		    FROM image
		    WHERE imageType = '상품'
		    GROUP BY articleNo
		) i ON p.productNo = i.articleNo
		WHERE p.rn = 1
		  AND p.productName LIKE '%' || #{keyword} || '%'
	</select>

[Jackson 라이브러리 추가]

<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.8.5</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-core-asl</artifactId>
			<version>1.8.5</version>
		</dependency>

9️⃣[myHomeFome.jsp] - 선택한 상품 미리보기 생성

//선택된 상품 미리보기
let selectedProducts = []; 

function prodPreView(product) {
    const previewArea = document.getElementById("prodPreview");
    
    // 중복선택 방지
    for (let i = 0; i < selectedProducts.length; i++) {
        if (selectedProducts[i].productNO === product.productNO) {
            alert("이미 선택한 상품입니다!");
            return;
        }
    }
    
        selectedProducts.push(product);
        
        // 기존 "선택한 상품이 없습니다." 메시지가 있다면 지움
        const existingMsg = document.getElementById("noProdMsg");
        if (existingMsg) {
            previewArea.removeChild(existingMsg);
        }

    
    
        const container = document.createElement("div");
        container.style.display = "flex";
        container.style.alignItems = "center";
        container.style.gap = "10px";
        container.style.marginTop = "10px";

        // 썸네일 이미지
        const img = document.createElement("img");
        img.src =  "/gami/product/productThumbnail.do?articleNO=" + product.productNO + "&image=" + encodeURIComponent(product.imageFileName);
        img.alt = product.productName;
        img.width = 60;

        // 상품 이름
        const name = document.createElement("span");
        name.innerText = product.productName;
        
        // 삭제 버튼
        const delBtn = document.createElement("button");
        delBtn.innerText = "X";
        delBtn.style.marginLeft = "auto";
        delBtn.style.background = "none";
        delBtn.style.border = "none";
        delBtn.style.color = "#4D4D4D";
        delBtn.style.cursor = "pointer";
        delBtn.onclick = function(){
        	  selectedProducts = selectedProducts.filter(p => p.productNO !== product.productNO);
        	  previewArea.removeChild(container);
        	  
        	  // 상품 다 지워졌으면 메시지 다시 보여주기
              if (selectedProducts.length === 0) {
                  const noProd = document.createElement("p");
                  noProd.id = "noProdMsg"; // 메시지 id 부여!
                  noProd.innerText = "선택한 상품이 없습니다.";
                  previewArea.appendChild(noProd);
              }      	     
        };
        container.appendChild(img);
        container.appendChild(name);
        container.appendChild(delBtn);
        previewArea.appendChild(container);  
}

document.addEventListener("DOMContentLoaded", function () {
    const previewArea = document.getElementById("prodPreview");
    const noProd = document.createElement("p");
    noProd.id = "noProdMsg";
    noProd.innerText = "선택한 상품이 없습니다.";
    previewArea.appendChild(noProd);
});