Files
sake/build/resources/main/static/mobile/js/bnft/cpslmkn/CpslmknCreateGame.js

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('재시작 요청 중 오류가 발생했습니다. 다시 시도해주세요.');
}
});
}