D+76::SHOP_수량변경후 자동변경,장바구니 상품에 대한 수량 및 가격 갱신,선택삭제 //파이썬_튜플

Am.Vinch·2022년 10월 17일
0

20221017_mon

실습내용

  • 장바구니목록페이지에서 수량변경 입력 후 변경버튼 클릭시, 디비반영과 수량도 update되지만, 옆 가격 영역과 하단의 총가격영역은 자동으로 변경되지 않는다.(페이지이동해야 변경된다.) 때문에 다시 Ajax를 사용해 자동변경되도록 만들어준다.
    1. 변경버튼 클릭시 모달창의 취소를 누르면 변경전 input태그에 있던 값으로 변경되어야한다.
      : 방법은 여러가지이다. 함수를 사용하거나 이벤트를 거는 방법이 있다.
    1. 주의할점)
      : 만약, input태그에 변경할 수량값을 입력 후 변경버튼을 클릭시, 모달창의 확인 버튼을 누르면 변경된 수량값이 뜨는데는 문제가 없지만, 다시 변경할 수량값을 input태그에 입력후 변경버튼을 클릭하여 모달창이 뜰 때, 취소버튼을 누르면 이전 변경된 값으로 나타나지는 것이 아니라, 가장 처음 저장되어있는 value값으로 나타나진다. -> 이 부분을 해결해야한다!

Mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--해당 파일에 모든 쿼리문을 작성 -->
<mapper namespace="cartMapper">
 		<resultMap type="Kh.study.shop.cart.vo.CartVO" id="cart">
		<id column="CART_CODE" 	property="cartCode"/>
		<result column="ITEM_CODE" property="itemCode"/>
		<result column="MEMBER_ID" property="memberId"/>
		<result column="CART_AMOUNT" property="cartAmount"/>
		<result column="REG_DATE" property="regDate"/>
		<result column="TOTAL_PRICE" property="totalPrice"/>
		<!-- 내가 만든 ver. 그냥 변수추가하기  -->
		<result column="CATE_NAME" property="cateName"/>
		<result column="ITEM_NAME" property="itemName"/>
		<result column="ITEM_PRICE" property="itemPrice"/>
		<result column="ATTACHED_NAME" property="attachedName"/>
		
		<!-- 선생님 ver., cartVO에 itemVO 추가하기  -->
		<association property="itemVO" resultMap="itemMapper.item"></association>
		</resultMap>
	
	
	
	<resultMap type="Kh.study.shop.item.vo.CategoryVO" id="category">
		<id column="CATE_CODE"  	 property="cateCode"/>
		<result column="CATE_NAME"   property="cateName"/>
		<result column="CATE_STATUS" property="cateStatus"/>
	</resultMap>
	<resultMap type="Kh.study.shop.item.vo.ItemVO" id="item">
		<id column="ITEM_CODE" 	property="itemCode"/>
		<result column="ITEM_NAME" property="itemName"/>
		<result column="ITEM_PRICE" property="itemPrice"/>
		<result column="ITEM_COMMENT" property="itemComment"/>
		<result column="REG_DATE" property="regDate"/>
		<result column="ITEM_STOCK" property="itemStock"/>
		<result column="ITEM_STATUS" property="itemStatus"/>
		<result column="CATE_CODE" 	property="cateCode"/>
		 <association property="categoryVO" resultMap="adminMapper.category" /> 
		<collection property="imgList" resultMap="img"/>
	</resultMap>
	  <resultMap type="Kh.study.shop.item.vo.ImgVO" id="img">
		<id column="IMG_CODE" property="imgCode"/>
		<result column="ORIGIN_NAME" property="originName"/>
		<result column="ATTACHED_NAME" property="attachedName"/>
		<result column="IS_MAIN" property="isMain"/>
		<result column="ITEM_CODE" property="itemCode"/>
	</resultMap>  
	
<!--  장바구니 목록조회 -->
<!-- 장바구니를 reg_date를 조회할 때 주의할 점: 반드시 장바구니에 등록한 날짜를 기준으로 해야한다. -->
<!-- 장바구니등록된 날짜 : C.REG_DATE -->	
<select id="selectCartList" resultMap="cart">
	SELECT CART_CODE
            ,IT.CATE_CODE
            ,CATE_NAME
			,C.ITEM_CODE
			,ITEM_NAME
			,MEMBER_ID
			,CART_AMOUNT
			,TO_CHAR(C.REG_DATE,'YYYY-MM-DD') REG_DATE
			,ITEM_PRICE
			,TOTAL_PRICE
			,ATTACHED_NAME
	FROM SHOP_CART C,SHOP_ITEM IT,ITEM_IMG IM,ITEM_CATECGORY CT
	WHERE C.ITEM_CODE = IT.ITEM_CODE
    AND C.ITEM_CODE = IM.ITEM_CODE
    and IT.CATE_CODE = CT.CATE_CODE
	AND IS_MAIN = 'Y'
	AND MEMBER_ID = #{memberId}
  	ORDER BY CART_CODE DESC
</select>


<!-- 장바구니 등록 (같은 상품이어도 별도로 등록됨)-->
<!-- totalPrice : 단가 * 수량 = 단가 * #{cartAmount} -->
<!-- 단가 : 서브쿼리로 구한다. -->
<!-- <insert id="regCart">
	<selectKey resultType="String" keyProperty="cartCode" order="BEFORE">
		SELECT 'CART_' ||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(CART_CODE,6))),0)+1,3,0)
 		FROM SHOP_CART
	</selectKey>
	INSERT INTO SHOP_CART
		(   CART_CODE
			,ITEM_CODE
			,MEMBER_ID
			,CART_AMOUNT
			,TOTAL_PRICE
		) VALUES (
			#{cartCode},#{itemCode},#{memberId},#{cartAmount}
			, (SELECT ITEM_PRICE FROM SHOP_ITEM WHERE ITEM_CODE = #{itemCode}) * #{cartAmount}
			)
</insert> -->


<!-- 장바구니 등록쿼리 Merge 사용(같은상품끼리 자동 업데이트 묶어서 등록) -->
<insert id="regCart">
	<selectKey resultType="String" keyProperty="cartCode" order="BEFORE">
		SELECT 'CART_'|| LPAD(NVL(MAX(TO_NUMBER(SUBSTR(CART_CODE, 6))), 0) +1, 3, 0) FROM SHOP_CART
	</selectKey>
	MERGE INTO SHOP_CART
	   USING DUAL
	   ON(ITEM_CODE = #{itemCode} AND MEMBER_ID = #{memberId})
	
	   WHEN MATCHED THEN
	   UPDATE 
	   SET
	      CART_AMOUNT = CART_AMOUNT + #{cartAmount}
	     , TOTAL_PRICE = (CART_AMOUNT + #{cartAmount}) * 
	        			 (SELECT ITEM_PRICE FROM SHOP_ITEM WHERE ITEM_CODE = #{itemCode})
	   WHERE MEMBER_ID = #{memberId}
	   AND ITEM_CODE = #{itemCode}    
	
	   WHEN NOT MATCHED THEN
	
	   INSERT(   CART_CODE
	         , ITEM_CODE
	         , MEMBER_ID
	         , CART_AMOUNT
	         , TOTAL_PRICE
	      )VALUES(
	           #{cartCode}
	         , #{itemCode}
	         , #{memberId}
	         , #{cartAmount}
	         , (SELECT ITEM_PRICE FROM SHOP_ITEM 
	            WHERE ITEM_CODE = #{itemCode}) * #{cartAmount}
	      )
</insert>


<!-- 재고 상품 수량 변경 -->
<!-- 수량이 바뀌면 총가격도 바뀌어야한다! 주의하기  -->
<!-- cat_code 값을 알면 item_Cdoe도 알수 있다! -> 이 점을 이용해서 이중서브쿼리문! -->
<update id="updateAmount">
	UPDATE SHOP_CART 
	SET 
	CART_AMOUNT = #{cartAmount}
	, TOTAL_PRICE = ( SELECT ITEM_PRICE 
					  FROM SHOP_ITEM 
	                  WHERE ITEM_CODE = 
						                 (
							                 SELECT ITEM_CODE
											 FROM SHOP_CART 
							                 WHERE CART_CODE = #{cartCode}
						                 )
	                 
	                 )
	                 * #{cartAmount}
	WHERE CART_CODE = #{cartCode}
</update>  

<!-- 장바구니 선택삭제 -->
<!-- 체크된 cartCode만 삭제하면된다.  -->
<!--  하지만 실제 코드는 조건절에  or 로 모든 cartCode를 연달아 적어야한다! -->
<!-- 그래서 or을 반복적으로 사용하는 대신 in 연산자를 사용한다 -->
<!-- 통상적으로는 배열로 던져저 배열로 받아 사용한다. -->
<!-- 클릭시 데이터들고 페이지 이동하는 방법은? -->
<!-- form태그와 location차이는 url경로에 데이터가 보이냐 안보이냐 차이다. -->
<!-- 컨트롤러에서 cartVO 던지는데, 여기서 getter호출한다. -> cartVO.getCartCodeList()를 가져와서 for문돌린다 -->
<!-- 그러면 foreach문이 해석이 되면, 아래처럼 해석이된다.-->

<!-- DELETE SHOP_CART
		WHERE CART_CODE IN
		                   (CART_001, CART_002, CART_003,...,)-->
	<delete id="deleteCarts">
		DELETE SHOP_CART
		WHERE CART_CODE IN
 		 <foreach collection="cartCodeList" item="cartCode" separator="," open="(" close=")" > 
			#{cartCode}
		 </foreach> 
	</delete>


<!-- 선택 구매 -->

</mapper> 

service

package Kh.study.shop.cart.service;

import java.util.ArrayList;
import java.util.List;

import Kh.study.shop.cart.vo.CartVO;

public interface CartService {
	//장바구니 조회
	List<CartVO> selectCartList(String memberId);
	//장바구니 등록
	void regCart(CartVO cartVO);
	//상품수량 변경
	void updateAmount(CartVO cartVO);
	//선택삭제
	void deleteCarts(CartVO cartVO);
}

serviceImpl

package Kh.study.shop.cart.service;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import Kh.study.shop.cart.vo.CartVO;

@Service("cartService")
public class CartServiceImpl implements CartService {
	@Autowired
	private SqlSessionTemplate sqlSession;

	@Override
	public List<CartVO> selectCartList(String memberId) {
		return sqlSession.selectList("cartMapper.selectCartList",memberId);
	}

	@Override
	public void regCart(CartVO cartVO) {
		sqlSession.insert("cartMapper.regCart",cartVO);
	}
	// 장바구니 상품 수량 변경
	@Override
	public void updateAmount(CartVO cartVO) {
		sqlSession.insert("cartMapper.updateAmount",cartVO);
	}
	//선택삭제
	@Override
	public void deleteCarts(CartVO cartVO) {
		sqlSession.delete("cartMapper.deleteCarts",cartVO);
	}
}

controller

package Kh.study.shop.cart.controller;
@Controller
@RequestMapping("/cart")
public class CartController {
	@Resource(name = "cartService")
	private CartService cartService;
	
	@ResponseBody //ajax사용 하니까
	@PostMapping("/regCart")
	public void regCart(CartVO cartVO ,Authentication authentication) {
		User user = (User)authentication.getPrincipal();
		cartVO.setMemberId(user.getUsername());
		cartService.regCart(cartVO);
		
		// ajax 사용하면 model 필요없다.
		// ajax 사용하니까 리턴 사용안함 -> return "content/cart/cart_list";
	}
	
	// ajax에서 if문으로 result값이 true일때 이동하는 페이지 경로
	@GetMapping("/cartList")
	public String cartList(Model model,Authentication authentication) {
		// memberId 값 가져와서 cartList에 같이 던져주기 
		User user = (User)authentication.getPrincipal();
		model.addAttribute("cartList",cartService.selectCartList(user.getUsername())) ;
		
		
		// 전체 총 가격 데이터 (리스트에서 뽑아서 누적합으로 데이터 던져주기)
		int finalPrice = 0;
		for(CartVO e : cartService.selectCartList(user.getUsername())) {
			finalPrice = finalPrice + e.getTotalPrice();
		}
		model.addAttribute("finalPrice",finalPrice);
		
		return "content/cart/cart_list";
	}
	
	//선택삭제
	@PostMapping("/deleteCart")
	public String deleteCarts(String cartCodes) {//"cart_001,cart_002,cart_003"
		String[] cartCodeArr = cartCodes.split(",");// 위처럼 넘어오는 cartCodes를 쉼표',' 로 분리한다. 그럼 문자열이 여러개나와서 배열로 받아야한다.
		List<String> cartCodeList= Arrays.asList(cartCodeArr);
		
		CartVO cartVO = new CartVO();//커맨드객체로 넘겨주려면 미리 cartVO에 cartCodes가 있으면 가능하다
		cartVO.setCartCodeList(cartCodeList);
		
		//cartCodeArr 안에 있는 cartCode를 하나하나 꺼내서 넣어준다.-> 반복문사용 
		//for(String cartCode : cartCodeArr) {
			//cartCodeList.add(cartCode);
		//}
		cartService.deleteCarts(cartVO);
		
		return "redirect:/cart/cartList";
	}
}
		

html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
	xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout" 
	layout:decorate="~{layout/base_layout}"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
	
<div layout:fragment="content">
	<!-- 제목줄 -->
	<div class="row mb-5">
		<div class="col">
		 <h1>CART LIST</h1>
		 </div>
	</div>
	
	<!-- 장바구니 목록 테이블  -->
	<div class="row ">
		<div class="col ">
			 <table style="width: 100%;" class="table table-striped table-hover">
				 <colgroup>
					<col width="*%" >
					<col width="5%" >
					<col width="15%" >
					<col width="20%" >
					<col width="25%" >
					<col width="20%" >
					<col width="20%" >
				</colgroup> 
				<thead style="font-size: 20px; font-weight: bold; color: #425F57;">
					<tr >
						<td><input type="checkbox" id="allChk" checked="checked"></td>
						<td>No.</td>
						<td colspan="2" style="text-align: center;">상품 정보</td>
						<td>수량</td>
						<td>가격</td>
						<td>등록 일자</td>
					</tr>
				</thead>
				
				
				<tbody align="center" style="text-align: justify;">
	 			<th:block th:if="${#lists.size(cartList) == 0}">
			 		<div> 장바구니에 등록된 상품이 없습니다.</div>
			   	</th:block> 
			   	
			   	  <th:block th:unless="${#lists.size(cartList) == 0}">
						<th:block th:each="cart : ${cartList}" > 
							<tr> <!-- 만약, td태그 밖에서 데이터 화면에 나타나게한다면? -> [[${cart.cateName}]] -->
								<td><input  th:value="${cart.cartCode}"  type="checkbox" class="chk"  checked="checked"></td>
								<!-- 역순으로 순서 뽑는 방법 : 전체갯수 - index -->
								<!-- 순서(No) 뽑는방법 : [[${cartStat.index}]] 이용 -->
								<!-- 차례대로 순서 뽑는방법 : <th:block th:each="cart , status : ${cartList}" >  <td th:text="${status.count}">  -->
								<td>
									<span th:text="${#lists.size(cartList) - cartStat.index}"></span> 
								</td>
								<td ><img width="100px;" height="140px;" th:src="|@{/images/}${cart.attachedName}|">   </td>
								<td > 
									[<span style="color: #749F82;" th:text=" ${cart.cateName}"></span>]
									<span th:text=" ${cart.itemName}" ></span> 
								</td>
								<td >
									<input id="cartAmounts" type="number" min="0" th:value="${cart.cartAmount}" th:data-origin-amount="${cart.cartAmount}"><!-- value값은 화면에 보이는 값을 data-...보이지않는 값에 넣어준다. -->   
									<!-- 내가 클릭한 변경버튼의 해당하는 그 상품수량 숫자값을 들고오기위해 this 사용! -->
									<button type="button" class="btn btn-light" th:onclick="goUpdateAmount(this);">변경</button>
								</td>
								<td><!-- (다른방법) [[${cart.itemVO.itemPrice}]]*[[${cart.cartAmount}]]  -->
								 <div class="row">
								 	<div class="col-6">
										 <div><span>[[${#numbers.formatCurrency(cart.itemPrice)}]]</span>*<span>[[${cart.cartAmount}]]</span>&nbsp;=</div><!-- 공백 표시 문자 기호 한칸띄어쓰기 -->
								 	</div>
								 	<div class="col-6">
										 <div class="totalPriceDiv" style="font-style: italic; font-weight: bold;"th:text="${#numbers.formatCurrency(cart.totalPrice)}" th:data-total-price="${cart.totalPrice}"> </div>	
								 	</div>
								 </div>
								</td>
								<td th:text="${cart.regDate}"> </td>
							</tr>
					 	</th:block>  
			   	</th:block> 				
				</tbody>
				
			</table>
		 </div>
	</div>
	
	<!-- 하단 영역 -->
		<!-- 총가격 -->
		<div class="row mt-5 mb-1" >
			<div class="col-3"></div><!-- 줄맞춤용도 -->
			<div class="col-3"></div><!-- 줄맞춤용도 -->
			<div class="col-3"></div><!-- 줄맞춤용도 -->
			<div class="col-3">
				 <div  class="input-group mb-3 " >
				  <span class="input-group-text" id="inputGroup-sizing-default">
					  총가격 
				  </span>
				  <div id="finalPriceTag" style="text-align: right;" th:data-total-price="${finalPrice}"   th:text=" ${#numbers.formatCurrency(finalPrice)}"  class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default"></div>
				</div>
			</div>
		</div>

		<!-- 삭제 및 구매 버튼 -->
		<div class="row mb-10" >
			 <div class="col" align="right">

					<!-- 보이지않은 형태로 체크된 cartCode들을 form으로 보내줘야한다. -->
					<form th:action="@{/cart/deleteCart}" method="post" id="deleteCartForm">
						<input type="hidden" name="cartCodes" value="">
						<!-- 바로 submit으로 보내지않고 함수를 실행해서 비어있는 value값을 데리고 와서 보내줘야한다 -->
						<button th:onclick="goDelete();" type="button" class="btn btn-outline-danger">선택 삭제</button>
					</form>

					<button th:onclick="goBuy();" class="btn btn-outline-warning" style="color: #FF9F29;">선택 구매</button>
			</div> 
		</div>
		
<!-- 수량변경 modal 창  -->		
<div class="modal fade" id=updateAmountModal tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
     <div class="modal-dialog">
       <div class="modal-content">
         <div class="modal-body">
            <div class="row mb-3">
               <div class="col">
                  <div>상품 수량 변경을 하시겠습니까?</div>
               </div>
            </div>
            <div class="row">
               <div class="col text-end">
              		   <!-- th:onclick="|location.href='@{컨트롤러경로}'|" -->
              		   <!-- js에서 데이터 보내려면, 태그를 잘 선택해서 받아서 사용하기위해 data- 속성이용해서 보내기. -->
	                <button id="updateAmountBtn" th:onclick="updateAmount();"  data-cart-code=""  data-cart-amount=""   type="button" class="btn  btn-sm"  style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: 3rem; --bs-btn-font-size: 1rem;">
	               	 	확인
	               	 </button>
	               	 <!-- 위 변경버튼 input에 있는 data-oring-amount값을 취소버튼 클릭시 세팅되도록 여기 data-oring-amount에 넣어줄거다 -->
	                <button data-origin-amount="" id="cancelBtn"type="button" th:onclick="rollbackAmount();"  class="btn btn-secondary btn-sm" data-bs-dismiss="modal" style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: 3rem; --bs-btn-font-size: 1rem;">
	               <!--  <button id="rollbackAmountBtn" type="button" th:onclick="rollbackAmount();"  data-cart-code=""  data-cart-amount=""  class="btn btn-secondary btn-sm" data-bs-dismiss="modal" style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: 3rem; --bs-btn-font-size: 1rem;"> -->
		                취소
	                </button>
               </div>
            </div>
         </div>
       </div>
     </div>
   </div>

<script src="https://code.jquery.com/jquery-latest.min.js"></script>	
<script type="text/javascript" th:src="@{/js/layout/cart_list.js}"></script>	
</div>
</html>

js

// [변수 선언] ------------------------------------------------------------------------//
//제목 행의 체크박스의 체크여부를 확인
const allChk = document.querySelector('#allChk');
//제목줄 제외 모든 체크박스
const chks = document.querySelectorAll('.chk');
//모달창(수량변경)
const updateAmountModal = new bootstrap.Modal('#updateAmountModal');




////////////////////////////// 이벤트 정의 영역 ///////////////////////////////////////////
//[이벤트 1] 체크박스 전체 선택
allChk.addEventListener('click',function(){// allchk 값은 하나만 있기 때문 이벤트 가능!

	const isChecked = allChk.checked;//체크된 제목줄 체크박스를 isChecked라고 한다.

	const chk = document.querySelectorAll('.chk');// 테이블의 체크된 체크박스 
	
	//제목 줄의 체크박스가 체크 됐다면..
	if(isChecked){//체크해ㅏㄹ
		for(i = 0; i<chk.length; i++){
			chk[i].checked = true;//체크된 클래스가 chk의 i번째 값은 true로 준다.
			
			
		}
		
	}
	else{//체크해제해라
		for(i = 0; i<chk.length; i++){
			chk[i].checked = false;//체크된 클래스가 chk의 값은 true로 준다.
		}
	}
	
	//전체 체크된 가격 총가격 나타내기
	setFinalPrice();
	
});


// [이벤트 2] 체크박스 전체해제 
	// event for문 밖 변수선언
	const chk = document.querySelectorAll('.chk');
	
	
	
	for(const e of chk){
		e.addEventListener('click',e=>{
			const cnt = chk.length; //제목줄 밑의 전체 체크박스의 갯수는 cnt
			const checkedCnt = document.querySelectorAll('.chk:checked').length; //클래스가 chk 인 것들 중에서 체크된것만 들고오겠다.그것의 갯수.
		
		if(cnt == checkedCnt){// 체크해라
			document.querySelector('#allChk').checked = true;
		}
		
		else{//체크하지마라
			document.querySelector('#allChk').checked = false;
					
		}	
		
	//전체 체크된 가격 총가격 나타내기
	//setFinalPrice();	
	});	
}

// [이벤트 3 ]장바구니 목록에 있는 체크박스 클릭 시 진행
// !!! 값이 여러개에 이벤트 불가능! -> for문돌려서 하나씩 빼서 여러번 실시한다.
for(const chk of chks){
	chk.addEventListener('click',function(){//체크박스 클릭시 실행
			setFinalPrice();//체크된 가격 하나씩 빼서 총가격 누적합계산하겠다.
		});
}












/////////////////////////////////////   [함수 정의]  ///////////////////////////////////////////////////////////////////////////
//[함수 3] 총가격을 세팅하는 함수
function setFinalPrice(){
			//체크된 박스 태그 선택
			const checkedBoxes = document.querySelectorAll('.chk:checked');
			
			//체크된 체크박스의 totalPrice 값 선택
			let finalPrice = 0;
			for(const checkBox of checkedBoxes){ // parseInt : 자바스크립트_숫자를 문자로 변환
			    const totalPrice =  parseInt(checkBox.closest('tr').querySelector('.totalPriceDiv').dataset.totalPrice);
			   
			    // 만약 data-totalprice로 데이터를 가져온다면?(th: 타임리프 사용해야 변수값 들고온다)
			    finalPrice = finalPrice + totalPrice;
			}
			//선택된 전체 값 더하기 
			// 천단위 구분 기호 : .toLocaleString()
		    document.querySelector('#finalPriceTag').innerText = '₩'+ finalPrice.toLocaleString()  ;
		    
}

// [함수 4 ] 수량변경 버튼 클릭시 진행되는 함수
function goUpdateAmount(selectedTag){// selectedTag :this로 넘어오는 태그(수량값의 변경버튼 클릭한 태그 의미)
	updateAmountModal.show();//맨위에 선언한 변수 모달을 가져와 열어주도록 한다.        
	
	// 수량값과 카트코드값을 들고와야하기때문에 태그 선택해서 가져오기! 어떻게?
	// 클릭한 버튼의 data-cart-code, data-cart-amount 속성의 값을 수량을 변경하고자하는 데이터로 세팅
	// 내가 지금 클릭한 태그의 바로 옆에있는 input태그의 수량값 들고오자. -> this 사용하기
	
	// this 를 사용하면?
	// selectedTag를 기준으로 원하는 태그를 찾아갈 수 있어 용이하다!
	
    // - 수량 (cartAmount)
    // --1) input태그 number값으로 수량 태그 선택시 :
	const cartAmount = selectedTag.closest('tr').querySelector('input[type="number"]').value;
	// --2) id값으로 수량 태그 선택시 : const cartAmountB = selectedTag.querySelector('#cartAmounts').value;

	// - 카트코드 (cartCode): 체크박스에다가 카트코드 부여하기 value값으로
	const cartCode = selectedTag.closest('tr').querySelector('input[type="checkbox"]').value;

	// - 변경된 수량 태그선택
	//const itemPrice = document.querySelector('#itemPriceTag').value;
	//alert(itemPrice);
	
	// data- 속성값에 위에서 선택한 태그값들을 바로 넣어준다. 
	document.querySelector('#updateAmountBtn').dataset.cartCode = cartCode;//cart-code
	document.querySelector('#updateAmountBtn').dataset.cartAmount = cartAmount;//cart-amount
	//document.querySelector('#updateAmountBtn').dataset.itemPrice = cartAmount;
	
	//기존 장바구니 수량(originAmount)을 취소버튼에 전달한다.
	const originAmount = selectedTag.closest('tr').querySelector('input[type="number"]').dataset.originAmount;//origin-amount
	document.querySelector('#cancelBtn').dataset.originAmount = originAmount;
}

// [함수 5] 수량버튼 클릭 후, 나타나는 모달창의 확인버튼 클릭시, 진행되는 함수 
function updateAmount(){// 여기 괄호안 매개변수는 html연결된 데이터! 
	const cartCode   = document.querySelector('#updateAmountBtn').dataset.cartCode;
	const cartAmount = document.querySelector('#updateAmountBtn').dataset.cartAmount;
	//const itemPrice = document.querySelector('#updateAmountBtn').dataset.itemPrice;

	$.ajax({
         url: '/cart/updateAmount', //요청경로
         type: 'post',
		// 여기 데이터는 controller에서 던져받는 데이터!
         data: {'cartCode':cartCode 
         		,'cartAmount':cartAmount}, //필요한 데이터
         success: function(result) {
        	alert('성공');
        	//주의!! 모달창은 알아서 닫히지않는다. 페이지이동을 하지않은 이상! 때문에 코드를 직접 써서 닫아줘야한다.
        	updateAmountModal.hide();
        	
        	//모달창이 닫히자마자 input태그 입력한 상품수량값으로 테이블 옆줄의 수량영역도 바뀌어야 한다. 
        	//장바구니 상품에 대한 수량 및 가격 갱신
        	// : 이 또한 제목줄 제외 모든 체크박스를 하나씩 빼서 비교
        	// : 실제로 수정되어 저장된 카트코드(cartAmount)와 일치하면 바꾼다.
        	 for(const chk of chks){
				if(chk.value == cartCode){
					chk.closest('tr').querySelector('input[type="number"]').dataset.originAmount = cartAmount;
				}
			
			 }
			
			
         },
         error: function() {
            alert('실패');
         }
      });
}

// 수량변경 모달(팝업)창에서 취소 버튼 클릭 시 진행되는 함수
function rollbackAmount(){
	// 이미 수량 변경버튼을 클릭하면, 변경할 상품의 cartCode값을 가지고는 있다.
	// 그런데 이는 모달창에 뜨는 '확인'버튼에 갖고있다.
	// 그래서 이를 반복문으로 비교하여 일치하면 그 줄에 있는 수량을 롤백시켜야하는 원래 값으로 돌려준다.
	 
	// 제묵줄 제외한 모든 체크박스에 반복문 접근하여 cartCode 가져온다.
	//수량을 롤백시켜야하는 cartCode와 비교
	
	const selectedCartCode = document.querySelector('#updateAmountBtn').dataset.cartCode;
	const originAmount = document.querySelector('#cancelBtn').dataset.originAmount;
	
	for(const chk of chks){//이 chk의 밸류값이 체크박스의 cartCode와 같다. -> th:value="${cart.cartCode}"	
		
		// 반복문을 돌리면서 비교하는데, 내가 변경하고픈 체크박스의 input태그의 cart코드와 일치하다면	
		if(chk.value == selectedCartCode){
			//수량을 원래대로 돌려야하는 input태그를 찾아가서 원래 수량값으로 돌려줘야한다.
			chk.closest('tr').querySelector('input[type="number"]').value = originAmount;		
			//하지만, 문제점발생
			// 실제로 수량변경 후 다시 취소버튼을 클릭하면 변경한값으로 나타나는 것이아니라 무조건 첫번째 저장된 originAmount값만 뜬다.		
		}
	}
	
	//실제로 수량변경이 완료되면	
}
// [함수 2 ] 선택삭제 클릭 시	
function goDelete(){
	const deleteForm = document.querySelector('#deleteCartForm');	
	//체크한 cartCode 다 들고 온다.(cartCode값은 체크박스안에  value값과 같다)
	const checkedChks = document.querySelectorAll('.chk:checked');

	//--선택한 상품이 없을 때
	const checkedCnt = document.querySelectorAll('.chk:checked').length;	
	if(checkedCnt == 0){
		alert('선택한 상품이 없습니다.');		
		return ;
	}
	
	//--선택된 체크박스들 있을 때
	//데이터를 주고받을 땐, 문자열로 만드는게 가장 편하다.
	let cartCodes = '';//우선,빈문자로 만든다.
	for(const checkedChk of checkedChks){
		cartCodes = cartCodes + checkedChk.value + ',';// "CART_001,CART_002,CART_003"
	}	
	
	deleteForm.querySelector('input').value = cartCodes; //빈 value값에 위에서 만든 문자열 cartCodes값을 채워준다.
	//cartCodes =cartCodes.substr(0,cartCodes.length-1);//가져가서 사용할땐 문자열을 잘라줘야한다.
	
	deleteForm.submit();// (데이터넘기며 페이지이동 방법 2) form태그 사용시 :선택 삭제 form태그에 바로 submit주지않고 button으로 준다음 이렇게 value값 가져온 후 여기서 submit주면된다.
	
	
	
	
	

}














//내가 가져온 소스
//---------------------------------------------------------------------------------------//

// [함수 1]  선택구매버튼을 클릭시
function goBuy(){
	const checkedCnt = document.querySelectorAll('.chk:Checked').length;//체크박스들중에서 체크된 것들만!(all)그것의 갯수.
	
	if(checkedCnt == 0){
		alert('선택한 상품이 없습니다.');		
		return ;
	}
	
	const checkedBoxes = document.querySelectorAll('.chk:checked'); // 여러개가지고 오니까 all 사용
	let totalPrice = 0; // 변하기때문 let 사용한다.
	let itemCodes = ''; // 변하기때문 let 사용한다.
	let cartAmounts = ''; // 변하기때문 let 사용한다.
	let cartCodes = ''; // 변하기때문 let 사용한다.

	
	
	for(const checkBox of checkedBoxes){//체크된 checkedBoxes들 중에 하나씩 뺀다 그것을 checkBox 라고한다.
		
		totalPrice = totalPrice + parseInt(price); 
		//상품코드 값 선택 후 누적합 계산
		const itemCode = checkBox.value;
		itemCodes = itemCodes + itemCode +',';//ITEM_001,ITEM_002, 
		
		//구매수량 값 선택 후 누적합 계산
		const cartAmount = checkBox.closest('tr').children[4].innerText; 
		cartAmounts = cartAmounts + cartAmount +',';
		
		//카테고리코드 값 선택 후 누적 합 계산
		const cartCode= checkBox.dataset.cartcode;//jsp에서 cartCode이지만 js는 항상 소문자로 가져오기때문에 소문자로 작성해야 오류발생x
		console.log(checkBox.dataset);// 개발자콘솔창확인시, data-cart-code/data-cartCode(data-cartcode) 의 차이점 파악하기위해 
		cartCodes = cartCodes + cartCode +',';//CART_001.CART_002,..
	
	}
	document.querySelector('form[action="insertBuys.buy"]').submit();
}	
//


	
	


		

결과

  • input태그에 수량입력 후 '변경'버튼 클릭시, 모달창이 띄워지면서 확인과 취소버튼을 클릭할 수 있다.
    : 확인 버튼을 클릭하면, 변경되어 값이 나타나지만, 취소버튼을 클릭하면, 변경되기 직전의 값이 input태그에 나타난다.
  • 첫화면
  • input태그에 수량 '50'으로 입력 후 변경버튼 클릭시 모달 창이 뜬다.

  • 취소버튼 클릭 시, 원래 값이 돌아와 input태그에 나타나진다.
  • 확인버튼 클릭 시, input태그에 입력한 값이 나타나진다.


다음 실습내용

  • buy_info.html
    - 주문 정보(No. 상품명 상품대표이미지 가격(단가) 수량) -> 목록으로 띄운다.
    : 가장마지막은 총 구매액 띄운다.
    - 주문자 정보() : id, 이름 , 연락처, 주소
    : 화면 가장 아래 주문확인 버튼 만들기
    : 버튼 클릭 시, db에 insert 완료시키기
profile
Dev.Vinch

0개의 댓글