/** * CpslmknCreateGame.js * * 캡슐 메이킹 게임의 게임 생성 및 진행 기능을 관리하는 모듈 * 사용자가 잎/도토리를 모아 캡슐을 생성하고 단계별로 완성해 나가는 기능 구현 */ /** * 문서 로드 완료 시 초기화 및 이벤트 바인딩 * 페이지 로드 시 UI 초기화 및 모든 이벤트 리스너 설정 */ $(document).ready(function() { // MicroModal 기본 초기화 (여기서 한 번만 수행) MicroModal.init({ disableScroll: true, awaitCloseAnimation: true // onShow, onClose 등 콜백은 여기서 정의 X }); // 기존 헤더 버튼 비활성화 및 새 버튼 추가 initializeHeaderButtons(); // 버블 효과 생성 // 화면에 움직이는 버블 애니메이션 요소를 동적으로 추가 createBubbles(); // 플라스크 애니메이션 적용 // 각 플라스크 요소에 애니메이션 효과 적용, 각 요소마다 다른 시간 간격으로 이미지 전환 $('.flask1, .flask2, .flask3, .flask4, .flask5, .line1, .line2, .line3').each(function(index) { animateFlask($(this), [300, 1000, 200, 300, 500, 500, 300, 300][index]); }); // 초록잎/도토리 넣기 버튼 이벤트 리스너 $('#cntGameItem').on('click', useLeaf); // 초록잎/도토리 모으기 버튼 이벤트 리스너 $('.btn.sm.outline.theme2').on('click', goToCollectPage); // 클립 버튼 이벤트 리스너 $(document).off('click', '#currentProgressButton').on('click', '#currentProgressButton', function() { const bnfInnb = $('#bnfInnb').val() || $('input[name="bnfInnb"]').val(); if (!bnfInnb) { console.error('bnfInnb 값을 찾을 수 없습니다.'); alert('게임 정보를 불러올 수 없습니다.'); return; } $.ajax({ url: '/sopmal/bnft/capsuleGameInfo', type: 'POST', data: { bnfInnb: bnfInnb }, dataType: 'json', success: function(response) { if (response && response.resBody) { try { const result = JSON.parse(response.resBody.result); console.log("서버에서 받은 원본 데이터:", result); // 디버깅용 // 모달 데이터 구성 // 게이지 바 계산에 필요한 데이터 추가 const modalData = { progressInfo: { progrsStep: result.currentProgressStep, totUseLeafCnt: result.totalUsedLeaf || result.totUseLeafCnt || 0, requiredLeaf: result.requiredLeaf || 100, stepProgressPercentage: result.stepProgressPercentage || 0 }, productName: result.rewardProductName, productDesc: result.rewardProductDesc || result.productDescription || '', thumbnailPath: result.productImagePath, cdnurl: $('#cdnurl').val() || '', sopmalCd: $('#sopmalCd').val(), importantNotice: { notice1: result.notice1 || $('#importantNotice').val() || '', notice2: result.notice2 || '', notice3: result.notice3 || '' } }; console.log("모달에 전달할 데이터:", modalData); // 디버깅용 // 먼저 모달 표시 MicroModal.show('modal-1'); // 그 다음에 모달 내용 업데이트 (모달이 DOM에 추가된 후 업데이트해야 함) setTimeout(function() { if (typeof updateModalContent === 'function') { updateModalContent(modalData); } else { console.error('updateModalContent 함수를 찾을 수 없습니다.'); alert('화면을 업데이트 할 수 없습니다.'); } }, 100); } catch (e) { console.error('JSON 파싱 오류:', e, response.resBody.result); alert('진행 상태 데이터를 처리하는 중 오류가 발생했습니다.'); } } else { const errorMessage = (response && response.resBody && response.resBody.message) ? response.resBody.message : '서버 응답 오류 또는 데이터 없음'; console.error('데이터 로드 실패:', errorMessage, response); alert(`진행 상태를 불러오는데 실패했습니다. (${errorMessage})`); } }, error: function(xhr, status, error) { console.error('AJAX 요청 실패:', status, error); alert('진행 상태를 불러오는 중 오류가 발생했습니다.'); } }); }); // 설정 버튼 이벤트 리스너 $('#CapsuleettingsButton').on('click', function(e) { e.preventDefault(); goToSettingsPage(); }); // "다른 선물로 다시 시작" 버튼 이벤트 리스너 (modal-1 내부에 있음) // data-micromodal-trigger="modal-2" 속성으로 처리되므로 별도 핸들러 불필요할 수 있음 // 단, CpslmknCreateGameModal.js 에서 #modal-2의 '처음부터 다시시작' 버튼 핸들러는 필요 $(document).on('click', '#modal-2 .microModal__btn:first-child', function() { // resetCapsule 함수는 CpslmknCreateGameModal.js 에 정의됨 if (typeof resetCapsule === 'function') { resetCapsule(); } else { console.error('resetCapsule 함수를 찾을 수 없습니다.'); } }); // 페이지 로드 시 해시 체크 // URL에 해시가 있으면 해당 ID의 모달 열기 if (window.location.hash) { var modalId = window.location.hash.replace('#', ''); openModal(modalId); } // 페이지 로드 시 초기 상태 설정 // 게임 진행 상태를 서버에서 가져오거나 세션스토리지에서 복원 initializeGameStatus(); // 모달 닫기 버튼 이벤트 리스너 추가 // 모달 닫기 버튼 클릭 시 해당 모달 닫기 $('.microModal__close2').on('click', function() { const modalId = $(this).closest('.microModal').attr('id'); MicroModal.close(modalId); }); }); /** * 버블 애니메이션 요소를 생성하여 화면에 추가하는 함수 * 다양한 크기와 위치, 애니메이션 속도를 가진 버블을 생성 */ function createBubbles() { // 버블 설정 배열 - 각 버블의 크기, 위치, 지연시간, 애니메이션 지속시간 정의 const bubbles = [ { size: 12, left: '20%', bottom: '-10%', delay: 0, duration: 3 }, { size: 10, left: '60%', bottom: '10%', delay: 0.6, duration: 2.8 }, { size: 8, left: '30%', bottom: '30%', delay: 0.4, duration: 2.6 }, { size: 6, left: '70%', bottom: '50%', delay: 1, duration: 2.4 }, { size: 4, left: '40%', bottom: '70%', delay: 0.8, duration: 2.2 }, { size: 2, left: '50%', bottom: '90%', delay: 1.2, duration: 2 } ]; // 각 버블 설정에 따라 DOM 요소 생성 및 스타일 적용 $.each(bubbles, function(index, bubble) { $('
') .addClass('bubble') .css({ width: bubble.size, height: bubble.size, left: bubble.left, bottom: bubble.bottom, animationDuration: bubble.duration + 's', animationDelay: bubble.delay + 's' }) .appendTo('#bubbleContainer'); }); } /** * 플라스크 요소에 애니메이션 효과를 적용하는 함수 * @param {jQuery} $flaskElement - 애니메이션을 적용할 플라스크 요소 * @param {number} interval - 이미지 전환 간격(밀리초) */ function animateFlask($flaskElement, interval) { // 플라스크 내부의 모든 이미지 요소 선택 const $images = $flaskElement.find('.svgContainer img'); let currentIndex = 0; // 다음 이미지를 표시하는 내부 함수 function showNextImage() { $images.eq(currentIndex).hide(); // 현재 이미지 숨기기 currentIndex = (currentIndex + 1) % $images.length; // 다음 이미지 인덱스 계산(순환) $images.eq(currentIndex).show(); // 다음 이미지 표시 } // 초기 상태 설정: 모든 이미지 숨기고 첫 번째 이미지만 표시 $images.hide().eq(0).show(); // 지정된 간격으로 이미지 전환 타이머 설정 setInterval(showNextImage, interval); } /** * 완료 모달의 진행 상태 표시를 업데이트하는 함수 * @param {number} currentStep - 현재 진행 단계(1~5) * @param {number} progressPercent - 현재 단계의 진행률(0~100) */ function updateCompleteModalProgress(currentStep, progressPercent) { // 모달 내부 진행바 요소 선택 const $modalGameStatusBar = $('#modal-1 .gameStatusBar'); // 모든 단계 표시에서 .on 클래스 제거 (초기화) $modalGameStatusBar.find('.step01, .step02, .step03, .step04, .last').removeClass('on'); // 현재 단계까지의 모든 단계에 .on 클래스 부여 (활성화) // switch문의 fall-through 특성을 활용하여 현재 단계까지 모든 단계 활성화 switch (currentStep) { case 5: $modalGameStatusBar.find('.last').addClass('on'); // 5단계 /* falls through */ case 4: $modalGameStatusBar.find('.step04').addClass('on'); // 4단계 /* falls through */ case 3: $modalGameStatusBar.find('.step03').addClass('on'); // 3단계 /* falls through */ case 2: $modalGameStatusBar.find('.step02').addClass('on'); // 2단계 /* falls through */ case 1: $modalGameStatusBar.find('.step01').addClass('on'); // 1단계 break; default: // 정상 단계가 아닐 경우 처리 X break; } // 진행 바의 너비를 진행률에 맞게 조정 $modalGameStatusBar.find('.per').css('width', `${progressPercent}%`); } /** * 게임 상태를 초기화하는 함수 * 새로고침 여부에 관계없이 JSP hidden 값을 사용하여 초기화 */ function initializeGameStatus() { // JSP에서 전달받은 hidden 값들로 게임 상태 구성 const gameStatusFromHidden = { ownedLeafCount: parseInt($('#leafCount').val()) || 0, currentStep: parseInt($('#currentStep').val()) || parseInt($('#progressStep').val()) || 1, stepProgressPercentage: parseFloat($('#stepProgressPercentage').val()) || 0, isStepCompleted: false }; console.log('Hidden 값으로부터 구성된 게임 상태:', gameStatusFromHidden); // UI 업데이트 및 세션스토리지에 상태 저장 updateGameUI(gameStatusFromHidden); sessionStorage.setItem('gameStatus', JSON.stringify(gameStatusFromHidden)); } /** * 게임 UI를 업데이트하는 함수 * @param {Object} data - 게임 상태 데이터 객체 * @param {number} data.ownedLeafCount - 보유 아이템 수 * @param {number} data.currentStep - 현재 진행 단계(1~5) * @param {number} data.stepProgressPercentage - 현재 단계의 진행률(0~100) * @param {boolean} data.isStepCompleted - 현재 단계 완료 여부 */ function updateGameUI(data) { // 데이터 null 체크 - 데이터가 없으면 함수 종료 if (!data) { console.error('데이터가 없습니다'); return; } // 안전한 값 할당 - 기본값 설정으로 undefined/null 방지 const safeData = { ownedLeafCount: data.ownedLeafCount || 0, currentStep: data.currentStep || 1, stepProgressPercentage: data.stepProgressPercentage || 0, isStepCompleted: data.isStepCompleted || false }; // 아이템 개수 UI 업데이트 - 아이콘 유지하면서 개수만 변경 const itemIcon = $('#ContingItem i').attr('class') || 'ico_leaf'; $('#ContingItem').html(`${safeData.ownedLeafCount}개`); // 진행률 표시 업데이트 const displayPercentage = data.stepProgressPercentage; // 진행 바 너비 및 텍스트 업데이트 $('.percentage-bar').css('width', `${displayPercentage}%`); $('.per-txt').text(`${Math.floor(displayPercentage)}% 채웠어요.`); $('.per-flask span').text(`${safeData.currentStep}단계`); // 플라스크 이미지 클래스 업데이트 - 현재 단계에 맞는 이미지 표시 $('.bar-container') .removeClass((index, className) => { // 정규식으로 flask0숫자 패턴의 모든 클래스 찾아 제거 return (className.match(/(^|\s)flask0\d+/g) || []).join(' '); }) .addClass(`flask0${safeData.currentStep}`); // 세션스토리지 업데이트 - 최신 상태 저장 sessionStorage.setItem('gameStatus', JSON.stringify(safeData)); // 모달 진행 상황 업데이트 updateCompleteModalProgress(safeData.currentStep, displayPercentage); // 5단계 완성 여부 확인 및 버튼 비활성화 처리 // 최종 단계(5단계)가 100% 완료되면 버튼 비활성화 및 텍스트 변경 if (safeData.currentStep === 5 && safeData.stepProgressPercentage >= 100) { // 버튼 비활성화 $('#cntGameItem') .prop('disabled', true) .addClass('disabled') .text('캡슐 제작 완료!'); // 자동으로 완료 모달 표시 (기존 코드 수정) setTimeout(() => { // 현재 혜택 정보로 모달 데이터 구성 const bnfInnb = $('#bnfInnb').val() || $('input[name="bnfInnb"]').val(); if (!bnfInnb) { console.error('bnfInnb 값을 찾을 수 없습니다.'); return; } // 서버에서 최신 완료 정보 가져와서 모달 표시 $.ajax({ url: '/sopmal/bnft/capsuleGameInfo', type: 'POST', data: { bnfInnb: bnfInnb }, dataType: 'json', success: function(response) { if (response && response.resBody) { try { const result = JSON.parse(response.resBody.result); // 완료 상태 모달 데이터 구성 const modalData = { progressInfo: { progrsStep: 5, // 완료 단계 totUseLeafCnt: result.totalUsedLeaf || result.totUseLeafCnt || 0, requiredLeaf: result.requiredLeaf || 100, stepProgressPercentage: 100 // 완료 상태 }, productName: result.rewardProductName, productDesc: result.rewardProductDesc || result.productDescription || '', thumbnailPath: result.productImagePath, cdnurl: $('#cdnurl').val() || '', sopmalCd: $('#sopmalCd').val(), importantNotice: { notice1: result.notice1 || $('#importantNotice').val() || '', notice2: result.notice2 || '', notice3: result.notice3 || '' } }; // 완료 모달 자동 표시 MicroModal.show('modal-1'); // 모달 내용 업데이트 setTimeout(function() { if (typeof updateModalContent === 'function') { updateModalContent(modalData); } else { console.error('updateModalContent 함수를 찾을 수 없습니다.'); } }, 100); } catch (e) { console.error('JSON 파싱 오류:', e); } } }, error: function(xhr, status, error) { console.error('완료 정보 로드 실패:', error); } }); }, 1000); // 1초 후 자동 표시 } } /** * 아이템(잎/도토리)을 사용하여 게임을 진행하는 함수 * 서버에 사용 요청을 보내고 결과에 따라 UI 업데이트 */ function useLeaf() { // 현재 보유한 잎 개수 확인 - 텍스트에서 숫자만 추출 const currentLeafCount = parseInt($('#ContingItem').text().replace(/[^0-9]/g, '')); // 잎이 없는 경우 토스트 메시지 표시 후 함수 종료 if (currentLeafCount <= 0) { // 수정: CSS .show 클래스를 이용한 토스트 표시 $('#acorn_toast').addClass('show'); setTimeout(() => { $('#acorn_toast').removeClass('show'); }, 2000); return; } // 사용할 잎 개수 계산 (10개 이상이면 10개, 미만이면 1개) // 한 번에 최대 10개까지 사용 가능 const useLeafCnt = currentLeafCount >= 10 ? 10 : 1; // 서버 요청 데이터 구성 const requestData = { bnfInnb: $('#bnfInnb').val(), // 혜택 고유번호 bnfSttusInnb: $('#bnfSttusInnb').val(), // 혜택 상태 고유번호 useLeafCnt: useLeafCnt // 사용할 아이템 개수 }; // 서버에 아이템 사용 요청 $.ajax({ url: '/sopmal/bnft/useLeaf', type: 'POST', contentType: 'application/json', data: JSON.stringify(requestData), success: function(response) { // 서버 응답 데이터 파싱 const resultData = JSON.parse(response.resBody.result); // 초록잎 부족 오류 처리 if (resultData.leafUsageSuccess === false) { if (resultData.errorCode === 'INSUFFICIENT_LEAF') { // 초록잎 부족 시 보유량 업데이트 및 알림 표시 const ownedLeafCount = resultData.ownedLeafCount || 0; // UI에 정확한 보유량 반영 const itemIcon = $('#ContingItem i').attr('class') || 'ico_leaf'; $('#ContingItem').html(`${ownedLeafCount}개`); // 수정: CSS .show 클래스를 이용한 토스트 표시 $('#acorn_toast').addClass('show'); setTimeout(() => { $('#acorn_toast').removeClass('show'); }, 2000); } else { // 기타 오류 처리 const errorMessage = resultData.errorMessage || '잎 사용에 실패했습니다.'; showCustomAlert(errorMessage); } return; } // 수정: 성공 조건을 gameCompleted 또는 currentStep으로 변경 if (resultData.gameCompleted || resultData.currentStep) { // 현재 단계 데이터 구성 let currentStepData = { ...resultData, currentStep: resultData.currentStep, ownedLeafCount: resultData.ownedLeafCount // 서버에서 받은 최신 보유 개수 사용 }; // 수정: 게임 완료 조건 체크 if (resultData.gameCompleted || (resultData.currentStep === 5 && resultData.stepProgressPercentage >= 100)) { // 게임 완료 시 데이터 업데이트 currentStepData.isStepCompleted = true; currentStepData.stepProgressPercentage = 100; currentStepData.currentStep = 5; // 최종 단계로 설정 // UI 업데이트 updateGameUI(currentStepData); // 수정: 완료 모달 표시 로직 개선 setTimeout(() => { const bnfInnb = $('#bnfInnb').val() || $('input[name="bnfInnb"]').val(); if (!bnfInnb) { console.error('bnfInnb 값을 찾을 수 없습니다.'); return; } // 완료 상태 모달 데이터 구성 (서버에서 받은 데이터 사용) const modalData = { progressInfo: { progrsStep: 5, // 완료 단계 totUseLeafCnt: resultData.totalLeafUsed || 0, requiredLeaf: resultData.requiredLeaf || resultData.totalLeafNeeded || 1000, stepProgressPercentage: 100 // 완료 상태 }, productName: resultData.productName, productDesc: resultData.productDesc, thumbnailPath: resultData.imageUrl, cdnurl: $('#cdnurl').val() || '', sopmalCd: $('#sopmalCd').val(), importantNotice: { notice1: resultData.notice || $('#importantNotice').val() || '', notice2: '', notice3: '' } }; // 완료 모달 자동 표시 MicroModal.show('modal-1'); // 모달 내용 업데이트 setTimeout(function() { if (typeof updateModalContent === 'function') { updateModalContent(modalData); } else { console.error('updateModalContent 함수를 찾을 수 없습니다.'); } }, 100); }, 1000); // 1초 후 자동 표시 return; } // 단계 완료 여부 확인 및 처리 (5단계 미만인 경우) if (resultData.stepProgressPercentage >= 100) { // 단계 완료 시 데이터 업데이트 currentStepData.isStepCompleted = true; currentStepData.stepProgressPercentage = 100; // UI 업데이트 updateGameUI(currentStepData); // 중간 단계 완료 모달 처리 const stepNames = ['첫번째', '두번째', '세번째', '네번째', '다섯번째']; const currentStepName = stepNames[currentStepData.currentStep - 1]; // 완료 메시지 업데이트 $('#completionStepText').text(`${currentStepName} 유리병이 가득 찼어요!`); $('#completionFlask') .removeClass() .addClass(`ico_flask flask0${currentStepData.currentStep}`) .text(`${currentStepName} 유리병`); // 남은 단계 수 계산 및 표시 const remainingFlasks = 5 - currentStepData.currentStep; $('#remainingFlasks').text(remainingFlasks); // 모달 표시 전에 기존 이벤트 핸들러 제거 (중복 방지) $('#modal-2 .microModal__btn-primary').off('click'); // 단계 완료 모달 표시 MicroModal.show('modal-2'); // 단계 완료 모달의 "계속하기" 버튼에만 다음 단계 진행 이벤트 바인딩 $('#modal-2 .microModal__btn-primary').one('click', function() { // 모달 닫기 MicroModal.close('modal-2'); if (!resultData.gameCompleted) { // 모달이 완전히 닫힌 후에 다음 단계로 진행 setTimeout(() => { // 다음 단계 데이터 구성 const nextStepData = { ...currentStepData, currentStep: currentStepData.currentStep + 1, stepProgressPercentage: 0, isStepCompleted: false }; // UI 업데이트 updateGameUI(nextStepData); }, 300); } }); // "다시 시작" 버튼은 별도로 처리 (첫 번째 버튼) $('#modal-2 .microModal__btn:first-child').one('click', function() { // 다시 시작 확인 모달 표시 showRestartConfirmModal(); }); } else { // 단계가 완료되지 않은 경우 일반 UI 업데이트 updateGameUI(currentStepData); } } else { // 아이템 사용 실패 시 알림 표시 const errorMessage = resultData.errorMessage || '잎 사용에 실패했습니다. 다시 시도해주세요.'; showCustomAlert(errorMessage); } }, error: function(xhr, status, error) { // 서버 통신 오류 시 알림 표시 showCustomAlert('서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.'); } }); } /** * 아이템 수집 페이지로 이동하는 함수 * 현재 게임 상태를 세션스토리지에 저장 후 이동 */ function goToCollectPage() { // 현재 진행 상태 저장 - 수집 페이지에서 돌아올 때 복원하기 위함 const currentGameStatus = sessionStorage.getItem('gameStatus'); if (currentGameStatus) { sessionStorage.setItem('previousGameStatus', currentGameStatus); } // 모으기 페이지로 이동 window.location.href = '/sopmal/bnft/cpslmknCollectList'; } // 닫기 버튼 이벤트 리스너 // 모달 닫기 버튼 클릭 시 해당 모달 닫기 $('.microModal .microModal__close2').on('click', function () { var modalId = $(this).closest('.microModal').attr('id'); closeModal(modalId); }); // 뒤로가기 처리 // 브라우저 뒤로가기 버튼 클릭 시 모달 닫기 처리 window.addEventListener('popstate', function (event) { var modalId = window.location.hash.replace('#', ''); if (modalId) { closeModal(modalId); } else { // 해시가 없으면 모든 모달 닫기 $('.microModal').each(function () { MicroModal.close($(this).attr('id')); }); } // 본문 스크롤 복원 document.body.style.overflow = ''; }); /** * 헤더 버튼을 초기화하는 함수 * 기존 헤더의 검색/장바구니 버튼을 제거하고 게임용 버튼(진행상태/설정)으로 대체 */ function initializeHeaderButtons() { // 기존 헤더 버튼 중 검색 및 장바구니 아이콘 삭제 $('.header__btn').empty(); // 새로운 버튼 추가 const $headerBtns = $('.header__btn').parent(); const newButtons = ` `; $headerBtns.append(newButtons); } /** * 설정 페이지로 이동하는 함수 * 현재 혜택 내부번호를 유지하며 설정 페이지로 이동 */ function goToSettingsPage() { const bnfInnb = $('#bnfInnb').val(); // 혜택 내부번호 가져오기 const sopmalCd = $('#sopmalCd').val(); // 쇼핑몰 코드 가져오기 window.location.href = `/sopmal/bnft/settings?bnfInnb=${bnfInnb}`; // 설정 페이지로 이동 } /** * 진행 상태 바 생성 함수 * 게임 진행 단계와 진행률을 시각적으로 표시하는 상태 바 생성 * @param {number} progressStep - 현재 진행 단계 (1~5) * @param {number} progressPercent - 현재 진행률 (0~100) * @returns {jQuery} 생성된 상태 바 jQuery 객체 */ function createStatusBar(progressStep, progressPercent) { // 진행률을 정수로 변환하고 소수점 제거 const displayPercent = Math.floor(progressPercent); // 상태 바 DOM 구조 생성 및 반환 return $('
').addClass('gameStatusBarWrap') .append($('
').addClass('gameStatusBar') .append($('
').addClass('per').css('width', `${displayPercent}%`)) // 진행률 표시 바 .append($('').addClass('first').text('시작')) // 시작 지점 .append(createStepSpans(progressStep)) // 중간 단계 표시 .append($('').addClass(`last ${progressStep >= 5 ? 'on' : ''}`).text('5단계'))); // 마지막 단계 } /** * 단계 표시 span 생성 함수 * 진행 상태 바에 표시할 각 단계별 표시 요소 생성 * @param {number} currentStep - 현재 진행 단계 (1~5) * @returns {Array} 생성된 단계 표시 span jQuery 객체 배열 */ function createStepSpans(currentStep) { const spans = []; // 1~4단계 표시 생성 (5단계는 별도로 'last' 클래스로 처리) for (let i = 1; i <= 4; i++) { spans.push( $('') .addClass(`step0${i} ${currentStep >= i ? 'on' : ''}`) // 현재 단계 이하는 'on' 클래스 추가 .text(`${i}단계`) ); } return spans; } /** * 다른선물로 다시 시작 확인 모달을 표시하는 함수 * 모달을 표시하고 버튼에 적절한 이벤트 리스너 연결 */ function showRestartConfirmModal() { // 기존 이벤트 리스너 제거 (중복 방지) $('.microModal__btn').off('click'); // 모달 표시 MicroModal.show('modal-2', { onShow: function() { // URL 해시 추가 (브라우저 뒤로가기 처리용) if (window.location.hash !== '#modal-2') { window.history.pushState({ modal: 'open' }, '', '#modal-2'); } } }); // "처음부터 다시시작" 버튼에 이벤트 리스너 연결 $('#modal-2 .microModal__btn').first().on('click', function() { console.log("처음부터 다시시작 버튼 클릭됨"); MicroModal.close('modal-2'); // 사용자 선택 확정을 위한 두 번째 확인 모달 표시 showFinalConfirmModal(); }); // "그대로 계속할게요" 버튼에 이벤트 리스너 연결 $('#modal-2 .microModal__btn-primary').on('click', function() { console.log("그대로 계속하기 버튼 클릭됨"); MicroModal.close('modal-2'); // URL 해시 제거 window.history.replaceState({}, '', window.location.pathname); }); } /** * 최종 확인 모달을 표시하는 함수 * 정말로 다시 시작할지 확인하는 두 번째 모달 표시 */ function showFinalConfirmModal() { // 최종 확인 모달이 없으면 동적으로 생성 if ($('#modal-3').length === 0) { $('body').append(` `); } // 모달 표시 MicroModal.show('modal-3', { onShow: function() { // URL 해시 추가 window.history.pushState({ modal: 'open' }, '', '#modal-3'); } }); // 이벤트 리스너가 중복되지 않도록 먼저 제거 $('#restartFromBeginning').off('click'); // "다시 시작하기" 버튼에 이벤트 리스너 연결 $('#restartFromBeginning').on('click', function() { console.log("최종 다시 시작하기 버튼 클릭됨"); MicroModal.close('modal-3'); // 캡슐 선택 페이지로 이동 restartCapsule(); }); // "취소" 버튼에 이벤트 리스너 연결 $('#modal-3 .microModal__btn').first().on('click', function() { MicroModal.close('modal-3'); // URL 해시 제거 window.history.replaceState({}, '', window.location.pathname); }); } /** * 캡슐 제작을 처음부터 다시 시작하는 함수 * 서버에 재시작 요청을 보내고 캡슐 선택 페이지로 이동 */ function restartCapsule() { // 현재 혜택 고유번호 가져오기 const bnfInnb = $('#bnfInnb').val(); // 서버에 재시작 요청 보내기 $.ajax({ url: '/sopmal/bnft/resetCapsule', type: 'POST', contentType: 'application/json', data: JSON.stringify({ bnfInnb: bnfInnb }), success: function(response) { // 성공 시 캡슐 선택 페이지로 이동 window.location.href = '/sopmal/bnft/selectCapsule'; }, error: function(xhr, status, error) { // 오류 발생 시 토스트 메시지 표시 console.error('재시작 요청 실패:', error); alert('재시작 요청 중 오류가 발생했습니다. 다시 시도해주세요.'); } }); }