주문 페이지 스크립트

판매자별 테이블 접기 기능

document.addEventListener("DOMContentLoaded", function () {

    // 판매자별 테이블 접기
    const container = document.getElementById('tables-container');
    if (!container) return;

    const tables = Array.from(container.querySelectorAll('.order_content'));
    if (tables.length === 0) return;

    const vendorGroups = {};

    tables.forEach((table) => {
        const vendorElement = table.querySelector('.vendor-name');
        const vendor = vendorElement ? vendorElement.innerText.trim() : null;
        if (!vendor) return;

        if (!vendorGroups[vendor]) {
            vendorGroups[vendor] = [];
        }
        vendorGroups[vendor].push(table);
    });

    container.innerHTML = '';

    Object.entries(vendorGroups).forEach(([vendor, vendorTables]) => {
        const section = document.createElement('div');
        section.className = 'vendor-section';

        const header = document.createElement('div');
        header.className = 'vendor-header';

        const titleSpan = document.createElement('span');
        titleSpan.className = 'vendor-title';
        titleSpan.innerText = vendor;

        const iconSpan = document.createElement('span');
        iconSpan.className = 'vendor-toggle-icon';
        iconSpan.innerText = '▼';

        header.appendChild(titleSpan);
        header.appendChild(iconSpan);

        const group = document.createElement('div');
        group.className = 'vendor-group';

        vendorTables.forEach((table, i) => {
            if (i !== 0) {
                table.style.display = 'none';
            }
            group.appendChild(table);
        });

        header.addEventListener('click', () => {
            const isOpen = header.classList.toggle('open');
            iconSpan.innerText = isOpen ? '▲' : '▼';

            const allTablesInGroup = group.querySelectorAll('.order_content');
            allTablesInGroup.forEach((t, i) => {
                if (i === 0) return;
                t.style.display = isOpen ? 'table' : 'none';
            });
        });

        section.appendChild(header);
        section.appendChild(group);
        container.appendChild(section);
    });

기능 설명

각 상품 계산 기능

    // 각 상품 계산
    document.querySelectorAll('.order_content').forEach(table => {
        const row = table.querySelector('tr:nth-of-type(2)');
        if (!row) return;

        const originalEl = row.querySelector('.price_original');
        const saleEl = row.querySelector('.price_total');
        const discountEl = row.querySelector('.discount-rate');
        const quantityEl = row.querySelector('.quantity');

        const quantity = parseInt(quantityEl?.innerText || '1', 10);
        const originalUnit = parseInt(originalEl?.dataset.unit || '0', 10);
        const discountRate = parseFloat((discountEl?.innerText || '0').replace('%', '')) || 0;

        if (!isNaN(discountRate) && originalUnit > 0 && quantity > 0) {
            const original = originalUnit * quantity;
            originalEl.innerText = original.toLocaleString();

            const discountedUnitPrice = originalUnit * (1 - discountRate / 100);

            const flooredDiscountedUnitPrice = Math.floor(discountedUnitPrice);

            const sale = flooredDiscountedUnitPrice * quantity;
            saleEl.dataset.unit = sale;
            saleEl.innerText = sale.toLocaleString();

            const pointEl = row.querySelector('input.point');

            const discountedPriceForPoint = parseInt(saleEl?.dataset.unit || '0', 10);

            if (!isNaN(discountedPriceForPoint) && quantity > 0 && pointEl) {
                const userRank = pointEl.dataset.rank;

                let pointRate = 0;

                switch (userRank) {
                    case 'VVIP':
                        pointRate = 0.05;
                        break;
                    case 'VIP':
                        pointRate = 0.04;
                        break;
                    case 'GOLD':
                        pointRate = 0.03;
                        break;
                    case 'SILVER':
                        pointRate = 0.02;
                        break;
                    case 'FAMILY':
                        pointRate = 0.01;
                        break;
                    default:
                        pointRate = 0;
                        break;
                }
                const point = Math.floor(discountedPriceForPoint * pointRate);
                pointEl.value = point.toString();
            }
        }
    });

기능 설명

  1. 두 번째 <tr>(상품 정보 행) 선택

    const row = table.querySelector('tr:nth-of-type(2)');
    
    
  2. 수량 파싱

    • <td class="quantity"> 텍스트에서 숫자로 파싱 (quantity)
  3. 원가 단가 파싱

    • row.querySelector('.price_original').dataset.unit에서 originalUnit 추출
  4. 할인율 파싱

    • <td class="discount-rate"> 텍스트에서 % 제거 후 숫자로 파싱 (discountRate)
  5. 원가 합계 계산

    const original = originalUnit * quantity;
    originalEl.innerText = original.toLocaleString();
    
    
  6. 할인 단가 계산

    const discountedUnitPrice = originalUnit * (1 - discountRate / 100);
    const flooredDiscountedUnitPrice = Math.floor(discountedUnitPrice);
    const sale = flooredDiscountedUnitPrice * quantity;
    saleEl.dataset.unit = sale;
    saleEl.innerText = sale.toLocaleString();
    
    
  7. 포인트 적립 계산

    • input.point.dataset.rank에서 userRank 읽어옴

    • switch문으로 등급별 적립률 설정

      • VVIP: 5%
      • VIP: 4%
      • GOLD: 3%
      • SILVER: 2%
      • FAMILY: 1%
      • 그 외: 0%
    • const point = Math.floor(discountedPriceForPoint × pointRate) 계산 후

      pointEl.value = point.toString()

전체 포인트 요약 업데이트

    // 전체 포인트 요약 업데이트
    let totalEarnedPoint = 0;
    document.querySelectorAll('.point').forEach(pointEl => {
        const pointValue = pointEl?.value.replace(/[^\d]/g, ''); // value 속성에서 숫자만 추출
        console.log('pointValue:', pointValue); // 추출된 값 확인
        const point = parseInt(pointValue, 10);

        if (!isNaN(point)) {
            totalEarnedPoint += point;
        }
    });

    document.getElementById('summary-point').innerText = totalEarnedPoint.toLocaleString();
    document.querySelector('input[name="totalPoint"]').value = totalEarnedPoint;

기능 설명

  1. 모든 <input class="point"> 요소 순회

    document.querySelectorAll('.point').forEach(pointEl => { ... });
    
    
  2. 숫자만 추출 및 파싱

    const pointValue = pointEl.value.replace(/[^\d]/g, '');
    const point = parseInt(pointValue, 10);
    
    
  3. 유효한 숫자인 경우 누적

    if (!isNaN(point)) {
        totalEarnedPoint += point;
    }
    
    
  4. DOM 업데이트

    • #summary-point 요소에 totalEarnedPoint를 천 단위 콤마로 표시
    • 히든 필드 input[name="totalPoint"]에 동일한 값을 할당

쿠폰 모달 창 기능

    // 쿠폰 모달 창
    const modal = document.getElementById("couponModal");
    const showCouponModalButton = document.getElementById("showCouponModalButton");
    const closeButton = modal?.querySelector(".close-button");

    let selectedCouponBenefit = null;
    let previouslySelectedItem = null;
    let selectedCouponData = null;

    // 모달 열기 버튼 클릭
    if (showCouponModalButton && modal) {
        showCouponModalButton.onclick = function () {
            const vendorElements = document.querySelectorAll(".vendor-name");
            const vendorSet = new Set();
            vendorElements.forEach(el => vendorSet.add(el.textContent.trim()));

            const couponItems = document.querySelectorAll(".coupon-item");
            couponItems.forEach(item => {
                const issuedBy = item.getAttribute("data-issued-by")?.trim();
                const couponState = item.getAttribute("data-state")?.trim();

                // 발행자 일치 또는 관리자이고 미사용 상태인 경우만 보이도록
                item.style.display = (vendorSet.has(issuedBy) || issuedBy === "관리자") && couponState === "미사용"
                                     ? "block"
                                     : "none";
                item.classList.remove("selected");
                item.style.border = "1px solid #ccc";

                item.onclick = function () {
                    if (previouslySelectedItem) {
                        previouslySelectedItem.style.border = "1px solid #ccc";
                        previouslySelectedItem.classList.remove("selected");
                    }
                    this.classList.add("selected");
                    this.style.border = "2px solid red";

                    selectedCouponBenefit = this.querySelector("p")?.innerText;
                    previouslySelectedItem = this;

                    // 선택된 쿠폰 데이터 저장
                    selectedCouponData = {
                        issueNo: this.dataset.issueNo,
                        issuedBy: this.getAttribute("data-issued-by"),
                        benefit: selectedCouponBenefit
                    };
                };
            });

            // 모달 열릴 때마다 버튼 이벤트 다시 바인딩
            const applyCouponButton = modal.querySelector(".modal-buttons button");
            if (applyCouponButton) {
                applyCouponButton.onclick = function () {
                    if (selectedCouponData) {
                        document.getElementById("couponData").value = selectedCouponData.issueNo;
                        document.getElementById('summary-coupon-discount').innerText = '-' + selectedCouponData.benefit;
                        updateOrderSummary();
                        modal.style.display = "none";
                        selectedCouponBenefit = null;
                        previouslySelectedItem = null;
                        selectedCouponData = null;
                    } else {
                        alert("적용할 쿠폰을 선택해주세요.");
                    }
                };
            }
            modal.style.display = "block";
        };
    }

    // 모달 닫기 (× 버튼)
    if (closeButton && modal) {
        closeButton.onclick = function () {
            modal.style.display = "none";
            const couponItems = modal.querySelectorAll(".coupon-item");
            couponItems.forEach(item => {
                item.classList.remove("selected");
                item.style.border = "1px solid #ccc";
            });
        };
    }

    // 모달 외부 클릭 시 닫기
    window.onclick = function (event) {
        if (event.target === modal) {
            modal.style.display = "none";
            const couponItems = modal.querySelectorAll(".coupon-item");
            couponItems.forEach(item => {
                item.classList.remove("selected");
                item.style.border = "1px solid #ccc";
            });
        }
    };

기능 설명

결제 요약 업데이트 함수