819 lines
35 KiB
JavaScript
819 lines
35 KiB
JavaScript
/**
|
|
* 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) {
|
|
$('<div>')
|
|
.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(`<i class="${itemIcon}"></i>${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(`<i class="${itemIcon}"></i>${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 = `
|
|
<button class="header__btn" id="currentProgressButton">
|
|
<i class="icon icon_nav-capsule"></i>
|
|
<span class="visually-hidden">진행상태보기</span>
|
|
</button>
|
|
<button class="header__btn" id="CapsuleettingsButton">
|
|
<i class="icon icon_nav-set"></i>
|
|
<span class="visually-hidden">설정</span>
|
|
</button>
|
|
`;
|
|
|
|
$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 $('<div>').addClass('gameStatusBarWrap')
|
|
.append($('<div>').addClass('gameStatusBar')
|
|
.append($('<div>').addClass('per').css('width', `${displayPercent}%`)) // 진행률 표시 바
|
|
.append($('<span>').addClass('first').text('시작')) // 시작 지점
|
|
.append(createStepSpans(progressStep)) // 중간 단계 표시
|
|
.append($('<span>').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(
|
|
$('<span>')
|
|
.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(`
|
|
<div class="microModal microAlert" id="modal-3" aria-hidden="true">
|
|
<div class="microModal__overlay" tabindex="-1">
|
|
<div class="microModal__container" role="dialog" aria-modal="true">
|
|
<div class="microModal__body">
|
|
<div class="microModal__top">
|
|
<h2 class="microModal__title">
|
|
정말 처음부터 다시 시작하시겠습니까?
|
|
</h2>
|
|
</div>
|
|
<div class="microModal__content">
|
|
<p>
|
|
지금까지 진행한 내용이 모두 삭제됩니다.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="microModal__btnContainer">
|
|
<button class="microModal__btn" data-micromodal-close aria-label="창 닫기">취소</button>
|
|
<button class="microModal__btn microModal__btn-primary" id="restartFromBeginning">다시 시작하기</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`);
|
|
}
|
|
|
|
// 모달 표시
|
|
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('재시작 요청 중 오류가 발생했습니다. 다시 시도해주세요.');
|
|
}
|
|
});
|
|
}
|