merge master into develop - CscListRForm.jsp FAQ 아코디언 버그 수정
This commit is contained in:
@@ -0,0 +1,345 @@
|
||||
// 출석체크 관련 기능을 담당하는 즉시 실행 함수
|
||||
const Atend = (function() {
|
||||
// 현재 날짜 정보
|
||||
const currentDate = new Date();
|
||||
const currentMonth = currentDate.getMonth();
|
||||
const currentYear = currentDate.getFullYear();
|
||||
const currentDay = currentDate.getDate();
|
||||
const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
|
||||
const firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();
|
||||
|
||||
// DOM 요소
|
||||
const daysContainer = document.querySelector(".days");
|
||||
const checkAttendanceButton = document.getElementById("check-attendance");
|
||||
|
||||
// 월 이름 배열
|
||||
const monthNames = ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"];
|
||||
|
||||
// 출석 일자 배열 (공백 제거 처리)
|
||||
const trimmedAttendanceDays = trimArrayElements(attendanceDays);
|
||||
|
||||
// 초기화 함수
|
||||
function init() {
|
||||
updateMonthTitle();
|
||||
generateCalendar();
|
||||
addEventListeners();
|
||||
loadImages();
|
||||
}
|
||||
|
||||
// 월 제목 업데이트
|
||||
function updateMonthTitle() {
|
||||
document.querySelector(".month-tit").textContent = monthNames[currentMonth];
|
||||
}
|
||||
|
||||
// 달력 생성
|
||||
function generateCalendar() {
|
||||
generateEmptyCells();
|
||||
generateDays();
|
||||
}
|
||||
|
||||
// 달력 앞부분 빈 셀 생성
|
||||
function generateEmptyCells() {
|
||||
for (let i = 0; i < firstDayOfMonth; i++) {
|
||||
const emptyCell = document.createElement("div");
|
||||
daysContainer.appendChild(emptyCell);
|
||||
}
|
||||
}
|
||||
|
||||
// 달력 일자 생성
|
||||
function generateDays() {
|
||||
for (let day = 1; day <= daysInMonth; day++) {
|
||||
const calendarDay = document.createElement("div");
|
||||
calendarDay.textContent = day;
|
||||
|
||||
const formattedDay = formatDate(currentYear, currentMonth + 1, day);
|
||||
|
||||
if (trimmedAttendanceDays.includes(formattedDay)) {
|
||||
calendarDay.classList.add("success");
|
||||
}
|
||||
|
||||
if (day === currentDay) {
|
||||
calendarDay.classList.add("today");
|
||||
}
|
||||
|
||||
daysContainer.appendChild(calendarDay);
|
||||
}
|
||||
}
|
||||
|
||||
// 이벤트 리스너 추가
|
||||
function addEventListeners() {
|
||||
checkAttendanceButton.addEventListener("click", handleAttendanceCheck);
|
||||
}
|
||||
|
||||
// 출석체크 처리
|
||||
function handleAttendanceCheck() {
|
||||
const formattedToday = formatDate(currentYear, currentMonth + 1, currentDay);
|
||||
|
||||
if (!trimmedAttendanceDays.includes(formattedToday)) {
|
||||
const attendanceCount = trimmedAttendanceDays.length + 1;
|
||||
const bnfRwdCateDvCd = getBenefitRewardCode(attendanceCount);
|
||||
|
||||
saveAttendance(formattedToday, bnfRwdCateDvCd);
|
||||
} else {
|
||||
openModal('modal-already-checked');
|
||||
}
|
||||
}
|
||||
|
||||
// 출석 정보 저장
|
||||
function saveAttendance(formattedToday, bnfRwdCateDvCd) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/participateAttendanceCheck',
|
||||
method: 'POST',
|
||||
contentType: 'application/json; charset=UTF-8',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: screenInfo.bnfInnb,
|
||||
mbrInnb: 87626, // 하드코딩된 회원 고유번호
|
||||
bnfPrtDt: formattedToday,
|
||||
mbrDvCd: 'GC', // 하드코딩된 회원 구분 코드
|
||||
bnfRwdCateDvCd: bnfRwdCateDvCd,
|
||||
bnfRwdGodsDvCd: '010'
|
||||
}),
|
||||
success: handleAttendanceSuccess(formattedToday),
|
||||
error: handleAttendanceError
|
||||
});
|
||||
}
|
||||
|
||||
// 출석 저장 성공 처리
|
||||
function handleAttendanceSuccess(formattedToday) {
|
||||
return function(response) {
|
||||
console.log('Attendance saved:', response);
|
||||
trimmedAttendanceDays.push(formattedToday);
|
||||
|
||||
updateCalendarUI();
|
||||
showAttendanceModal();
|
||||
getLatestAttendanceInfo();
|
||||
};
|
||||
}
|
||||
|
||||
// 출석 저장 실패 처리
|
||||
function handleAttendanceError(xhr, status, error) {
|
||||
console.error('Failed to save attendance:', error);
|
||||
alert('출석체크를 저장하는 데 실패했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
|
||||
// 달력 UI 업데이트
|
||||
function updateCalendarUI() {
|
||||
const todayElement = Array.from(daysContainer.children).find(child => child.textContent == currentDay);
|
||||
if (todayElement) {
|
||||
todayElement.classList.add("success");
|
||||
}
|
||||
}
|
||||
|
||||
// 출석 모달 표시
|
||||
function showAttendanceModal() {
|
||||
const attendanceCount = trimmedAttendanceDays.length;
|
||||
if (attendanceCount === 10) {
|
||||
openModal('modal-2');
|
||||
} else if (attendanceCount === 20) {
|
||||
openModal('modal-3');
|
||||
} else if (attendanceCount === daysInMonth) {
|
||||
openModal('modal-4');
|
||||
} else {
|
||||
openModal('modal-1');
|
||||
}
|
||||
}
|
||||
|
||||
// 최신 출석 정보 조회
|
||||
function getLatestAttendanceInfo() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/getLatestAttendanceInfo',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
mbrInnB: 87626,
|
||||
bnfInnb: screenInfo.bnfInnb
|
||||
}), // 하드코딩된 회원 고유번호
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function(response) {
|
||||
updateAttendanceInfo(response.attendanceCount, response.totalAttendanceMileage);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Failed to fetch latest attendance info:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 출석 정보 UI 업데이트
|
||||
function updateAttendanceInfo(attendanceCount, totalAttendanceMileage) {
|
||||
document.querySelector(".cnt1").textContent = `${attendanceCount}회`;
|
||||
document.querySelector(".cnt2").textContent = `${totalAttendanceMileage}원`;
|
||||
}
|
||||
|
||||
// 이미지 로딩
|
||||
function loadImages() {
|
||||
console.log('Starting to load images');
|
||||
loadImage('representative', screenInfo.representativeImagePath, $('.Att-bg img'));
|
||||
loadImage('reward', screenInfo.rewardImagePath, $('.eventAtt-banner img'));
|
||||
}
|
||||
|
||||
// 개별 이미지 로딩
|
||||
function loadImage(imageType, imagePath, $img) {
|
||||
if (!imagePath) {
|
||||
console.warn(`Image path for ${imageType} is not available`);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($img.length) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/image',
|
||||
method: 'GET',
|
||||
data: { path: imagePath, type: imageType },
|
||||
xhrFields: { responseType: 'blob' },
|
||||
success: function(data) {
|
||||
const imageUrl = URL.createObjectURL(data);
|
||||
$img.attr('src', imageUrl);
|
||||
console.log(`${imageType} image loaded successfully`);
|
||||
|
||||
if (imageType === 'reward') {
|
||||
updateRewardBannerLink();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
console.error(`Failed to load ${imageType} image`);
|
||||
$img.attr('src', '/path/to/fallback-image.jpg');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(`Image element not found for ${imageType}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 보상 배너 링크 업데이트
|
||||
function updateRewardBannerLink() {
|
||||
const $bannerLink = $('.eventAtt-banner a');
|
||||
if ($bannerLink.length && screenInfo.scrRwdLinkUrl) {
|
||||
$bannerLink.attr('href', screenInfo.scrRwdLinkUrl);
|
||||
console.log('Updated banner link URL:', screenInfo.scrRwdLinkUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// 유틸리티 함수들
|
||||
function trimArrayElements(arr) {
|
||||
return arr.map(element => element.replace(/[\[\]\s]/g, ''));
|
||||
}
|
||||
|
||||
function formatDate(year, month, day) {
|
||||
return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function getBenefitRewardCode(attendanceCount) {
|
||||
if (attendanceCount === 10) return '01020';
|
||||
if (attendanceCount === 20) return '01030';
|
||||
if (attendanceCount === daysInMonth) return '01040';
|
||||
return '01010';
|
||||
}
|
||||
|
||||
// 알림 상태 조회
|
||||
function getNotificationStatus() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/getNotificationStatus',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: screenInfo.bnfInnb }),
|
||||
success: function(response) {
|
||||
updateNotificationButton(response.notificationStatus);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('알림 상태 조회 실패:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 알림 버튼 업데이트
|
||||
function updateNotificationButton(isNotificationOn) {
|
||||
const $notificationBtn = $('.eventAtt__btnContainer .btn.outline.full');
|
||||
const $iconElement = $notificationBtn.find('i.ico_alarm');
|
||||
|
||||
if (isNotificationOn) {
|
||||
$notificationBtn.contents().filter(function() {
|
||||
return this.nodeType === 3; // Text nodes
|
||||
}).replaceWith('알림 신청 완료');
|
||||
$notificationBtn.data('action', 'cancel');
|
||||
} else {
|
||||
$notificationBtn.contents().filter(function() {
|
||||
return this.nodeType === 3; // Text nodes
|
||||
}).replaceWith('알림 신청');
|
||||
$notificationBtn.data('action', 'apply');
|
||||
}
|
||||
|
||||
// 아이콘 요소가 없으면 추가
|
||||
if ($iconElement.length === 0) {
|
||||
$notificationBtn.prepend('<i class="ico_alarm"></i>');
|
||||
}
|
||||
}
|
||||
|
||||
// 알림 신청/취소 처리
|
||||
function handleNotification(action) {
|
||||
const url = action === 'apply' ? '/sopmal/bnft/applyNotification' : '/sopmal/bnft/cancelNotification';
|
||||
$.ajax({
|
||||
url: url,
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: screenInfo.bnfInnb }),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
alert(action === 'apply' ? '알림 신청이 완료되었습니다.' : '알림 취소가 완료되었습니다.');
|
||||
getNotificationStatus();
|
||||
} else {
|
||||
alert(response.message || (action === 'apply' ? '알림 신청에 실패했습니다.' : '알림 취소에 실패했습니다.'));
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error(action === 'apply' ? '알림 신청 실패:' : '알림 취소 실패:', error);
|
||||
alert(action === 'apply' ? '알림 신청 중 오류가 발생했습니다.' : '알림 취소 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 초기화 및 이벤트 리스너
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
init();
|
||||
getNotificationStatus();
|
||||
|
||||
$(document).on('click', '.eventAtt__btnContainer .btn.outline.full', function(e) {
|
||||
e.preventDefault();
|
||||
const action = $(this).data('action');
|
||||
handleNotification(action);
|
||||
});
|
||||
});
|
||||
|
||||
// 공개 메서드
|
||||
return {
|
||||
getLatestAttendanceInfo: getLatestAttendanceInfo,
|
||||
getNotificationStatus: getNotificationStatus,
|
||||
handleNotification: handleNotification
|
||||
};
|
||||
})();
|
||||
|
||||
// 모달 관련 함수들
|
||||
function openModal(modalId) {
|
||||
MicroModal.show(modalId);
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
document.body.style.overflow = '';
|
||||
MicroModal.close(modalId);
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
|
||||
// 브라우저 뒤로가기 처리
|
||||
window.addEventListener('popstate', function(event) {
|
||||
var modalId = window.location.hash.replace('#', '');
|
||||
if (modalId) {
|
||||
closeModal(modalId);
|
||||
} else {
|
||||
document.querySelectorAll('.microModal').forEach(modal => {
|
||||
MicroModal.close(modal.id);
|
||||
});
|
||||
}
|
||||
document.body.style.overflow = '';
|
||||
});
|
||||
|
||||
// 페이지 로드 시 해시 체크
|
||||
if (window.location.hash) {
|
||||
var modalId = window.location.hash.replace('#', '');
|
||||
openModal(modalId);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
$(document).ready(function() {
|
||||
showItems();
|
||||
loadBannersSequentially().then(() => {
|
||||
initializeSlider();
|
||||
});
|
||||
});
|
||||
|
||||
const $benefitItems = $('.benefit-item');
|
||||
|
||||
function showItems() {
|
||||
$benefitItems.each(function(index, item) {
|
||||
setTimeout(function() {
|
||||
$(item).css({
|
||||
'transition': 'opacity 0.5s, transform 0.5s',
|
||||
'opacity': '1',
|
||||
'transform': 'translateY(0)'
|
||||
});
|
||||
}, index * 100);
|
||||
});
|
||||
}
|
||||
|
||||
function loadImage(banner) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = function() {
|
||||
resolve(img);
|
||||
};
|
||||
img.onerror = function() {
|
||||
console.error('Failed to load image:', banner.imagePath);
|
||||
reject(new Error(`Failed to load image: ${banner.imagePath}`));
|
||||
};
|
||||
img.src = banner.imagePath;
|
||||
});
|
||||
}
|
||||
|
||||
async function loadBannersSequentially() {
|
||||
const $bannerContainer = $('.benefit_main_banner');
|
||||
for (const banner of bannerData) {
|
||||
try {
|
||||
const img = await loadImage(banner);
|
||||
const $slide = $('<div>').addClass('benefit_bn');
|
||||
const $link = $('<a>').attr('href', banner.linkUrl);
|
||||
$(img).attr('alt', banner.bannerSj);
|
||||
$link.append(img);
|
||||
$slide.append($link);
|
||||
$bannerContainer.append($slide);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initializeSlider() {
|
||||
const $bannerWrap = $('.benefit_main_bannerWrap');
|
||||
if ($bannerWrap.length) {
|
||||
const $slides = $('.benefit_bn');
|
||||
const slideCount = $slides.length;
|
||||
let currentIndex = 0;
|
||||
let interval;
|
||||
|
||||
if (slideCount === 0) {
|
||||
console.warn('슬라이드가 없습니다');
|
||||
return;
|
||||
}
|
||||
|
||||
function showSlide(index) {
|
||||
$slides.hide();
|
||||
$slides.eq(index).show();
|
||||
updatePagination(index);
|
||||
}
|
||||
|
||||
function createPagination() {
|
||||
const $pagination = $('.pagination');
|
||||
$pagination.empty();
|
||||
for (let i = 0; i < slideCount; i++) {
|
||||
const $button = $('<button>').attr('data-index', i);
|
||||
$pagination.append($button);
|
||||
}
|
||||
}
|
||||
|
||||
function updatePagination(index) {
|
||||
$('.pagination button').removeClass('active')
|
||||
.eq(index).addClass('active');
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
currentIndex = (currentIndex + 1) % slideCount;
|
||||
showSlide(currentIndex);
|
||||
}
|
||||
|
||||
function startSliding() {
|
||||
interval = setInterval(nextSlide, 3000);
|
||||
}
|
||||
|
||||
function stopSliding() {
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
createPagination();
|
||||
showSlide(currentIndex);
|
||||
startSliding();
|
||||
|
||||
$('.pagination').on('click', 'button', function() {
|
||||
currentIndex = parseInt($(this).attr('data-index'));
|
||||
showSlide(currentIndex);
|
||||
});
|
||||
|
||||
$('.benefit_main_banner').on('click', nextSlide);
|
||||
|
||||
$bannerWrap.on('mouseenter', stopSliding)
|
||||
.on('mouseleave', startSliding);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// 앱-웹뷰 통신 API
|
||||
|
||||
// 전역 오염을 방지하기 위한 네임스페이스
|
||||
const AppWebviewAPI = (function() {
|
||||
// 비공개 변수 및 함수
|
||||
let pushKeyCallback = null;
|
||||
let pushReceiveCallback = null;
|
||||
let walkCountCallback = null;
|
||||
let pageActiveTimeCallback = null;
|
||||
|
||||
// JS102: 푸시 키 등록을 위한 콜백 처리
|
||||
function handlePushKeyRegist(tokenKey) {
|
||||
if (pushKeyCallback) {
|
||||
pushKeyCallback(tokenKey);
|
||||
}
|
||||
}
|
||||
|
||||
// JS105: 푸시 알림 터치에 대한 콜백 처리
|
||||
function handlePushReceive(pushType, data) {
|
||||
if (pushReceiveCallback) {
|
||||
pushReceiveCallback(pushType, data);
|
||||
}
|
||||
}
|
||||
|
||||
// JS106: 앱에서 걸음 수 가져오기
|
||||
function requestWalkCount() {
|
||||
if (window.webkit && window.webkit.messageHandlers.getWalkCount) {
|
||||
// iOS 웹뷰 호출
|
||||
window.webkit.messageHandlers.getWalkCount.postMessage({});
|
||||
} else if (window.Android && window.Android.getWalkCount) {
|
||||
// 안드로이드 웹뷰 호출
|
||||
window.Android.getWalkCount();
|
||||
}
|
||||
}
|
||||
|
||||
// JS107: 페이지 활성 시간을 앱에 전송
|
||||
function sendPageActiveTime(url, displaySeconds) {
|
||||
if (window.webkit && window.webkit.messageHandlers.sendPageActiveTime) {
|
||||
// iOS 웹뷰 호출
|
||||
window.webkit.messageHandlers.sendPageActiveTime.postMessage({
|
||||
url: url,
|
||||
displaySeconds: displaySeconds
|
||||
});
|
||||
} else if (window.Android && window.Android.sendPageActiveTime) {
|
||||
// 안드로이드 웹뷰 호출
|
||||
window.Android.sendPageActiveTime(url, displaySeconds);
|
||||
}
|
||||
}
|
||||
|
||||
// 공개 API
|
||||
return {
|
||||
// JS102: 푸시 키 등록을 위한 콜백 등록
|
||||
onPushKeyRegist: function(callback) {
|
||||
pushKeyCallback = callback;
|
||||
// 앱에서 호출할 수 있도록 전역 스코프에 콜백 노출
|
||||
window.callback_pushkey_regist = handlePushKeyRegist;
|
||||
},
|
||||
|
||||
// JS105: 푸시 알림 터치에 대한 콜백 등록
|
||||
onPushReceive: function(callback) {
|
||||
pushReceiveCallback = callback;
|
||||
// 앱에서 호출할 수 있도록 전역 스코프에 콜백 노출
|
||||
window.callback_push_receive_process = handlePushReceive;
|
||||
},
|
||||
|
||||
// JS106: 앱에서 걸음 수 요청
|
||||
getWalkCount: function(callback) {
|
||||
walkCountCallback = callback;
|
||||
requestWalkCount();
|
||||
},
|
||||
|
||||
// JS107: 페이지 활성 시간을 앱에 전송
|
||||
sendPageActiveTime: function(url, displaySeconds) {
|
||||
sendPageActiveTime(url, displaySeconds);
|
||||
},
|
||||
|
||||
// 앱에서 호출할 콜백 핸들러
|
||||
handleWalkCountResponse: function(count, date) {
|
||||
if (walkCountCallback) {
|
||||
walkCountCallback({ count: count, date: date });
|
||||
}
|
||||
},
|
||||
|
||||
// 추가적인 유틸리티 함수들을 여기에 추가할 수 있습니다.
|
||||
};
|
||||
})();
|
||||
|
||||
// 사용 예시:
|
||||
// AppWebviewAPI.onPushKeyRegist(function(tokenKey) { console.log('푸시 키 등록됨:', tokenKey); });
|
||||
// AppWebviewAPI.onPushReceive(function(pushType, data) { console.log('푸시 수신됨:', pushType, data); });
|
||||
// AppWebviewAPI.getWalkCount(function(result) { console.log('걸음 수:', result.count, '날짜:', result.date); });
|
||||
// AppWebviewAPI.sendPageActiveTime('https://example.com/best-reviews', 300);
|
||||
|
||||
// 걸음 수가 준비되었을 때 앱에서 호출할 함수
|
||||
// window.AppWebviewAPI.handleWalkCountResponse(10000, '20230101');
|
||||
@@ -0,0 +1,345 @@
|
||||
// Conrev.js
|
||||
const Conrev = (function() {
|
||||
let timer;
|
||||
let remainingTime;
|
||||
let currentEventId;
|
||||
let startTime;
|
||||
let reviewCheckInterval;
|
||||
let currentSlideIndex = 0;
|
||||
let reviewData = [];
|
||||
let lastViewedSlideIndex = 0;
|
||||
let reviewLayer;
|
||||
|
||||
function initializeSlider() {
|
||||
reviewData = window.reviewData || [];
|
||||
|
||||
const $slider = $('.reviewSlider ul');
|
||||
const $slides = $('.reviewSlider li');
|
||||
const slideCount = $slides.length;
|
||||
let currentSlide = 0;
|
||||
|
||||
// 페이지네이션 도트 추가
|
||||
const $pagination = $('.pagination');
|
||||
for (let i = 0; i < slideCount; i++) {
|
||||
$pagination.append('<div class="dot" data-slide="' + i + '"></div>');
|
||||
}
|
||||
$pagination.find('.dot').first().addClass('active');
|
||||
|
||||
// 슬라이드 이동 함수
|
||||
function moveSlide() {
|
||||
$slider.css('margin-left', -currentSlide * 100 + '%');
|
||||
$pagination.find('.dot').removeClass('active').eq(currentSlide).addClass('active');
|
||||
currentSlideIndex = currentSlide;
|
||||
updateReviewButton();
|
||||
}
|
||||
|
||||
// 이미지 로드
|
||||
loadImages();
|
||||
|
||||
// 페이지네이션 도트 클릭 이벤트
|
||||
$pagination.on('click', '.dot', function() {
|
||||
const newSlideIndex = $(this).data('slide');
|
||||
if (newSlideIndex !== lastViewedSlideIndex) {
|
||||
currentSlide = newSlideIndex;
|
||||
moveSlide();
|
||||
awardMileage();
|
||||
lastViewedSlideIndex = newSlideIndex;
|
||||
}
|
||||
});
|
||||
|
||||
// 마우스 드래그 이벤트
|
||||
let isDragging = false;
|
||||
let startPos = 0;
|
||||
let endPos = 0;
|
||||
|
||||
$slider.on('mousedown touchstart', function(e) {
|
||||
isDragging = true;
|
||||
startPos = e.pageX || e.originalEvent.touches[0].pageX;
|
||||
});
|
||||
|
||||
$(document).on('mouseup touchend', function(e) {
|
||||
if (isDragging) {
|
||||
endPos = e.pageX || e.originalEvent.changedTouches[0].pageX;
|
||||
const diff = endPos - startPos;
|
||||
if (Math.abs(diff) > 50) {
|
||||
currentSlide += (diff > 0) ? -1 : 1;
|
||||
if (currentSlide < 0) {
|
||||
currentSlide = slideCount - 1;
|
||||
} else if (currentSlide >= slideCount) {
|
||||
currentSlide = 0;
|
||||
}
|
||||
moveSlide();
|
||||
}
|
||||
isDragging = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 이미지 드래그 방지
|
||||
$('.reviewSlider img').on('dragstart', function(event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
// 링크 처리
|
||||
$slides.on('click', function() {
|
||||
const link = $(this).data('link');
|
||||
if (link) {
|
||||
window.location.href = link;
|
||||
}
|
||||
});
|
||||
|
||||
// 초기 버튼 설정
|
||||
updateReviewButton();
|
||||
}
|
||||
|
||||
function updateReviewButton() {
|
||||
if (reviewData.length > currentSlideIndex) {
|
||||
const currentReview = reviewData[currentSlideIndex];
|
||||
$('#reviewButton').off('click').on('click', function() {
|
||||
fetchReviewTime(currentReview.bnfInnb);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function fetchReviewTime(bnfInnb) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/getReviewTime',
|
||||
method: 'GET',
|
||||
data: { bnfInnb: bnfInnb },
|
||||
success: function(response) {
|
||||
if (response.success && response.tmeSecnd) {
|
||||
start(bnfInnb, reviewData[currentSlideIndex].linkUrl, response.tmeSecnd);
|
||||
} else {
|
||||
console.error('리뷰 시간 정보를 가져오는데 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
console.error('리뷰 시간 정보 요청 중 오류 발생:', textStatus, errorThrown);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function start(bnfInnb, linkUrl, seconds) {
|
||||
currentEventId = bnfInnb;
|
||||
remainingTime = seconds;
|
||||
startTime = new Date().getTime();
|
||||
|
||||
// 레이어 팝업 생성 및 표시
|
||||
createLayerPopup(linkUrl);
|
||||
$('#countdownTimer').show();
|
||||
startTimer();
|
||||
|
||||
reviewCheckInterval = setInterval(function() {
|
||||
if (!reviewLayer.is(':visible')) {
|
||||
stopTimer();
|
||||
$('#countdownTimer').hide();
|
||||
clearInterval(reviewCheckInterval);
|
||||
cancelMileageAward(); // 레이어가 닫히면 마일리지 적립 취소
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function createLayerPopup(linkUrl) {
|
||||
// 기존 레이어 제거
|
||||
if (reviewLayer) {
|
||||
reviewLayer.remove();
|
||||
}
|
||||
|
||||
// 새 레이어 생성
|
||||
reviewLayer = $('<div>', {
|
||||
id: 'reviewLayer',
|
||||
css: {
|
||||
position: 'fixed',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: '80%',
|
||||
height: '80%',
|
||||
backgroundColor: 'white',
|
||||
border: '1px solid black',
|
||||
zIndex: 1000
|
||||
}
|
||||
});
|
||||
|
||||
const header = $(`
|
||||
<header class="header header--sub">
|
||||
<div class="header__wrapper">
|
||||
<div class="header__controls-wrapper">
|
||||
<div class="header__controls">
|
||||
<div class="header__toBack">
|
||||
<button class="header__toBack__btn">
|
||||
<span class="visually-hidden">뒤로가기</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path fill="#1A1A1A" d="M16.598 3.338a.75.75 0 0 0-1.061 0l-8.132 8.131a.75.75 0 0 0 0 1.061l8.132 8.132a.75.75 0 0 0 1.06-1.06L8.998 12l7.6-7.602a.75.75 0 0 0 0-1.06Z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<h1 class="header__title">베스트 리뷰보기</h1>
|
||||
<div class="header__btn-container">
|
||||
<button class="header__btn"><i class="icon icon_nav-home"></i><span class="visually-hidden">메인으로</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
`);
|
||||
|
||||
const countdownToast = $(`
|
||||
<div class="topupPoint" style="position: fixed; top: 60px; left: 0; right: 0; z-index: 1001;">
|
||||
<span><i class="ico_clock"></i><b id="popupCountdown">${remainingTime}</b>초 동안 리뷰 보면 적립</span>
|
||||
</div>
|
||||
`);
|
||||
|
||||
const iframe = $('<iframe>', {
|
||||
src: linkUrl,
|
||||
css: {
|
||||
width: '100%',
|
||||
height: 'calc(100% - 60px)', // 헤더 높이만큼 빼기
|
||||
border: 'none',
|
||||
marginTop: '60px' // 헤더 아래에 위치
|
||||
}
|
||||
});
|
||||
|
||||
reviewLayer.append(header, countdownToast, iframe);
|
||||
$('body').append(reviewLayer);
|
||||
|
||||
// 뒤로가기 버튼 이벤트
|
||||
header.find('.header__toBack__btn').on('click', function() {
|
||||
closeLayerPopup();
|
||||
});
|
||||
|
||||
// 홈 버튼 이벤트
|
||||
header.find('.header__btn').on('click', function() {
|
||||
// 메인 페이지로 이동하는 로직
|
||||
window.location.href = '/main';
|
||||
});
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
updateTimerDisplay();
|
||||
|
||||
clearInterval(timer);
|
||||
timer = setInterval(function() {
|
||||
remainingTime--;
|
||||
updateTimerDisplay();
|
||||
|
||||
if (remainingTime <= 0) {
|
||||
clearInterval(timer);
|
||||
completeReviewViewing();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function closeLayerPopup() {
|
||||
if (reviewLayer) {
|
||||
reviewLayer.hide();
|
||||
stopTimer();
|
||||
cancelMileageAward();
|
||||
}
|
||||
}
|
||||
|
||||
function updateTimerDisplay() {
|
||||
$('#countdown, #popupCountdown').text(remainingTime);
|
||||
}
|
||||
|
||||
function completeReviewViewing() {
|
||||
let endTime = new Date().getTime();
|
||||
let duration = (endTime - startTime) / 1000;
|
||||
|
||||
if (duration >= remainingTime) {
|
||||
awardMileage();
|
||||
} else {
|
||||
cancelMileageAward();
|
||||
}
|
||||
|
||||
$('#countdownTimer').hide();
|
||||
}
|
||||
|
||||
function awardMileage() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/awardConrevMileage',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: reviewData[currentSlideIndex].bnfInnb }),
|
||||
success: function(response) {
|
||||
let result;
|
||||
try {
|
||||
result = JSON.parse(response);
|
||||
} catch (e) {
|
||||
result = response; // 이미 객체인 경우
|
||||
}
|
||||
|
||||
if (result.result === true) {
|
||||
alert('10원이 적립되었습니다!');
|
||||
} else {
|
||||
console.error('마일리지 적립 실패');
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
console.error('마일리지 적립 요청 중 오류 발생:', textStatus, errorThrown);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cancelMileageAward() {
|
||||
console.log('마일리지 적립이 취소되었습니다.');
|
||||
// 필요한 경우 서버에 마일리지 적립 취소 요청을 보낼 수 있습니다.
|
||||
}
|
||||
|
||||
function stopTimer() {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
if (reviewCheckInterval) {
|
||||
clearInterval(reviewCheckInterval);
|
||||
}
|
||||
}
|
||||
|
||||
// 이미지 로딩 함수
|
||||
function loadImages() {
|
||||
$('.reviewSlider .thum img').each(function(index) {
|
||||
const $img = $(this);
|
||||
const imgPath = $img.data('img-path');
|
||||
const imgName = $img.data('img-name');
|
||||
|
||||
if (imgPath && imgName) {
|
||||
loadImage(index, imgPath + imgName, $img);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 개별 이미지 로딩
|
||||
function loadImage(index, imagePath, $img) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/image',
|
||||
method: 'GET',
|
||||
data: { path: imagePath },
|
||||
xhrFields: { responseType: 'blob' },
|
||||
success: function(data) {
|
||||
const imageUrl = URL.createObjectURL(data);
|
||||
$img.attr('src', imageUrl);
|
||||
console.log(`Image ${index} loaded successfully`);
|
||||
},
|
||||
error: function() {
|
||||
console.error(`Failed to load image ${index}`);
|
||||
$img.attr('src', '/path/to/fallback-image.jpg');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: initializeSlider,
|
||||
start: start,
|
||||
stop: stopTimer,
|
||||
loadImages: loadImages
|
||||
};
|
||||
})();
|
||||
|
||||
// DOM이 로드된 후 슬라이더 초기화
|
||||
$(document).ready(function() {
|
||||
Conrev.init();
|
||||
});
|
||||
|
||||
// 창이 닫힐 때 타이머 정지
|
||||
$(window).on('beforeunload', function() {
|
||||
Conrev.stop();
|
||||
});
|
||||
@@ -0,0 +1,153 @@
|
||||
// 초기화 함수
|
||||
function initializeCapsuleSelection(data) {
|
||||
capsuleData = data;
|
||||
loadImages();
|
||||
setupProductSelection();
|
||||
setupModal();
|
||||
setupStartButton();
|
||||
}
|
||||
|
||||
// 이미지 로드 함수
|
||||
function loadImages() {
|
||||
document.querySelectorAll('.thum img').forEach((img, index) => {
|
||||
const product = capsuleData.productList[index];
|
||||
img.src = encodeURI(product.imgFilCours.replace(/\\/g, '/'));
|
||||
});
|
||||
}
|
||||
|
||||
// 제품 선택 기능 설정
|
||||
function setupProductSelection() {
|
||||
document.querySelectorAll('.gameProduct').forEach(product => {
|
||||
product.addEventListener('click', function() {
|
||||
document.querySelectorAll('.gameProduct').forEach(p => p.classList.remove('selected'));
|
||||
this.classList.add('selected');
|
||||
this.querySelector('input[type="radio"]').checked = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 모달 설정
|
||||
function setupModal() {
|
||||
MicroModal.init({
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true,
|
||||
});
|
||||
|
||||
// 풀스크린 팝업 트리거 이벤트 리스너
|
||||
document.querySelectorAll('.fullscreen-trigger').forEach(trigger => {
|
||||
trigger.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const modalId = this.getAttribute('data-micromodal-trigger');
|
||||
openModal(modalId);
|
||||
});
|
||||
});
|
||||
|
||||
// 풀스크린 팝업 닫기 이벤트 리스너
|
||||
document.querySelectorAll('.microModal .microModal__close').forEach(closeBtn => {
|
||||
closeBtn.addEventListener('click', function() {
|
||||
const modalId = this.closest('.microModal').id;
|
||||
closeModal(modalId);
|
||||
});
|
||||
});
|
||||
|
||||
// 풀스크린 팝업 뒤로가기 이벤트 리스너
|
||||
window.addEventListener('popstate', function(event) {
|
||||
const modalId = window.location.hash.replace('#', '');
|
||||
if (modalId) {
|
||||
closeModal(modalId);
|
||||
} else {
|
||||
document.querySelectorAll('.microModal').forEach(modal => {
|
||||
MicroModal.close(modal.id);
|
||||
});
|
||||
}
|
||||
document.body.style.overflow = '';
|
||||
});
|
||||
|
||||
// 페이지 로드 시 해시 체크
|
||||
if (window.location.hash) {
|
||||
const modalId = window.location.hash.replace('#', '');
|
||||
openModal(modalId);
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 열기 함수
|
||||
function openModal(modalId) {
|
||||
MicroModal.show(modalId, {
|
||||
onShow: function (modal) {
|
||||
if (window.location.hash !== '#' + modalId) {
|
||||
window.history.pushState({ modal: 'open' }, '', '#' + modalId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 모달 닫기 함수
|
||||
function closeModal(modalId) {
|
||||
document.body.style.overflow = '';
|
||||
MicroModal.close(modalId);
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
|
||||
// 만들기 시작 버튼 설정 함수
|
||||
function setupStartButton() {
|
||||
$('.bottomBtnControls .btn').on('click', function() {
|
||||
const selectedProduct = getSelectedProduct();
|
||||
if (selectedProduct) {
|
||||
updateModalContent(selectedProduct);
|
||||
openModal('modal-1');
|
||||
} else {
|
||||
alert('제품을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 추가 유틸리티 함수들
|
||||
function getSelectedProduct() {
|
||||
const selectedRadio = $('input[name="gameproduct"]:checked');
|
||||
if (selectedRadio.length) {
|
||||
const bnfInnb = selectedRadio.val();
|
||||
return capsuleData.productList.find(product => product.bnfInnb == bnfInnb);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 모달 내용 업데이트 함수
|
||||
function updateModalContent(product) {
|
||||
$('#modal-1 .microModal__title').html(`<b>${product.cnSj}</b><br>제품을 선택하셨네요.`);
|
||||
}
|
||||
|
||||
// 진행 상태 저장 또는 업데이트 함수
|
||||
function upsertProgressStatus(bnfInnb) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/upsertProgressStatus',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: bnfInnb }),
|
||||
success: function(response) {
|
||||
let result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
// 만들기 화면으로 이동
|
||||
window.location.href = '/sopmal/bnft/makeStartCapsule?bnfInnb=' + bnfInnb;
|
||||
} else {
|
||||
alert('진행 상태 저장에 실패했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('서버 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 페이지 로드 시 실행
|
||||
$(document).ready(function() {
|
||||
initializeCapsuleSelection(capsuleData);
|
||||
|
||||
// 모달의 '예' 버튼 클릭 이벤트
|
||||
$('#modal-1 .microModal__btn-primary').on('click', function() {
|
||||
const selectedProduct = getSelectedProduct();
|
||||
if (selectedProduct) {
|
||||
upsertProgressStatus(selectedProduct.bnfInnb);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
function initializeSpecialEventSlider() {
|
||||
const $slides = $('.specialEventSlider .innerIcon');
|
||||
const slideCount = $slides.length;
|
||||
let currentIndex = 0;
|
||||
let interval;
|
||||
|
||||
// Show the slide at the specified index
|
||||
function showSlide(index) {
|
||||
$slides.hide();
|
||||
$slides.eq(index).fadeIn();
|
||||
updatePagination(index);
|
||||
}
|
||||
|
||||
// Create pagination buttons dynamically
|
||||
function createPagination() {
|
||||
const $pagination = $('.pagination');
|
||||
$pagination.empty();
|
||||
for (let i = 0; i < slideCount; i++) {
|
||||
$pagination.append(`<button data-index="${i}"></button>`);
|
||||
}
|
||||
updatePagination(0);
|
||||
}
|
||||
|
||||
// Update active state of pagination buttons
|
||||
function updatePagination(activeIndex) {
|
||||
$('.pagination button').removeClass('active');
|
||||
$('.pagination button').eq(activeIndex).addClass('active');
|
||||
}
|
||||
|
||||
// Show the next slide
|
||||
function nextSlide() {
|
||||
currentIndex = (currentIndex + 1) % slideCount;
|
||||
showSlide(currentIndex);
|
||||
}
|
||||
|
||||
// Show the previous slide
|
||||
function previousSlide() {
|
||||
currentIndex = (currentIndex - 1 + slideCount) % slideCount;
|
||||
showSlide(currentIndex);
|
||||
}
|
||||
|
||||
// Start automatic sliding
|
||||
function startSliding() {
|
||||
interval = setInterval(nextSlide, 3000);
|
||||
}
|
||||
|
||||
// Stop automatic sliding
|
||||
function stopSliding() {
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
// Initialize the slider
|
||||
createPagination();
|
||||
showSlide(currentIndex);
|
||||
startSliding();
|
||||
|
||||
// Set up event handlers
|
||||
$('.capsuleCollectTop').hover(stopSliding, startSliding);
|
||||
$('.pagination').on('click', 'button', function() {
|
||||
currentIndex = $(this).data('index');
|
||||
showSlide(currentIndex);
|
||||
});
|
||||
|
||||
// Add click event to advance to the next slide
|
||||
$('.capsuleCollectTop').on('click', function() {
|
||||
nextSlide();
|
||||
});
|
||||
|
||||
// Touch events for mobile support
|
||||
let touchStartX = 0;
|
||||
let touchEndX = 0;
|
||||
|
||||
$('.capsuleCollectTop').on('touchstart', function(e) {
|
||||
touchStartX = e.originalEvent.touches[0].clientX;
|
||||
});
|
||||
|
||||
$('.capsuleCollectTop').on('touchend', function(e) {
|
||||
touchEndX = e.originalEvent.changedTouches[0].clientX;
|
||||
handleSwipe();
|
||||
});
|
||||
|
||||
function handleSwipe() {
|
||||
if (touchStartX - touchEndX > 50) {
|
||||
nextSlide(); // Left swipe
|
||||
} else if (touchEndX - touchStartX > 50) {
|
||||
previousSlide(); // Right swipe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
initializeSpecialEventSlider();
|
||||
});
|
||||
@@ -0,0 +1,336 @@
|
||||
$(document).ready(function() {
|
||||
// 버블 효과 생성
|
||||
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).on('click', '#currentProgressButton', function() {
|
||||
loadProgressModalData();
|
||||
});
|
||||
|
||||
// 설정 버튼 이벤트 리스너
|
||||
$('#CapsuleettingsButton').on('click', function(e) {
|
||||
e.preventDefault(); // 기본 동작 방지
|
||||
goToSettingsPage();
|
||||
});
|
||||
|
||||
// 진행 단계 모달 내의 "다른 선물로 다시 시작" 버튼 이벤트 리스너
|
||||
$('.btn.giftReset').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
showRestartConfirmModal();
|
||||
});
|
||||
|
||||
// 확인 모달의 "처음부터 다시시작" 버튼 이벤트 리스너
|
||||
$(document).on('click', '#restartFromBeginning', function() {
|
||||
console.log("처음부터 다시시작 버튼 클릭됨");
|
||||
MicroModal.close('modal-3');
|
||||
restartCapsule();
|
||||
});
|
||||
|
||||
// 새로 시작하기 버튼 이벤트 리스너
|
||||
$(document).on('click', '.newStartButton', function() {
|
||||
window.location.href = '/sopmal/bnft/selectCapsule';
|
||||
});
|
||||
|
||||
// 초기 게임 상태 설정
|
||||
updateGameStatus(initialGameStatus);
|
||||
|
||||
// MicroModal 초기화
|
||||
MicroModal.init({
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true,
|
||||
onShow: function(modal) {
|
||||
if (modal.id === 'modal-1') {
|
||||
resizeModal(modal);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 페이지 로드 시 해시 체크
|
||||
if (window.location.hash) {
|
||||
var modalId = window.location.hash.replace('#', '');
|
||||
openModal(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 }
|
||||
];
|
||||
|
||||
$.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');
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
function updateGameStatus(newStatus) {
|
||||
$('.percentage-bar').width(newStatus.progressPercent + '%');
|
||||
$('.per-flask span').text(newStatus.progressStep + '단계');
|
||||
$('.per-txt').text(newStatus.progressPercent + '% 채웠어요.');
|
||||
$('#ContingItem').html(`<i class="${shopCode === 'NC' ? 'ico_leaf' : 'ico_acorn'}"></i>${newStatus.remainingLeafCount}개`);
|
||||
$('.bar-container').attr('class', `bar-container flask0${newStatus.progressStep}`);
|
||||
$('#currentStep').text(newStatus.progressStep + '단계');
|
||||
}
|
||||
|
||||
function useLeaf() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/useLeaf',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
useLeafCnt: 10,
|
||||
bnfInnb: 81,
|
||||
progrsStep: initialGameStatus.progressStep // 현재 진행 단계 추가
|
||||
}),
|
||||
success: function(response) {
|
||||
let result = JSON.parse(response.resBody.result);
|
||||
if (result.success === true) {
|
||||
try {
|
||||
updateGameStatus(result);
|
||||
} catch (e) {
|
||||
showToast(result.error || '초록잎/도토리 사용에 실패했습니다.');
|
||||
}
|
||||
} else {
|
||||
showToast('서버 응답이 올바르지 않습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error:', error);
|
||||
showToast('서버와의 통신 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function restartCapsule() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/restartCapsule',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: 81 }), // bnfInnb 값은 실제 사용하는 값으로 변경해야 합니다.
|
||||
success: function(response) {
|
||||
let result = JSON.parse(response.resBody.result);
|
||||
if (result.success === true) {
|
||||
showToast('캡슐 만들기가 초기화되었습니다. 새로 시작합니다.');
|
||||
// 페이지 이동
|
||||
window.location.href = '/sopmal/bnft/selectCapsule';
|
||||
} else {
|
||||
showToast(response.message || '캡슐 만들기 초기화에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error:', error);
|
||||
showToast('서버와의 통신 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function showToast(message) {
|
||||
const $toast = $('#acorn_toast');
|
||||
$toast.text(message).addClass('show');
|
||||
setTimeout(() => {
|
||||
$toast.removeClass('show');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function goToCollectPage() {
|
||||
window.location.href = '/sopmal/bnft/cpslmknCollectList';
|
||||
}
|
||||
|
||||
function goToSettingsPage() {
|
||||
// URL에서 bnfInnb 값을 추출
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const bnfInnb = urlParams.get('bnfInnb');
|
||||
|
||||
// bnfInnb 값이 있으면 설정 페이지 URL에 추가
|
||||
let settingsUrl = '/sopmal/bnft/cpslmknSettings';
|
||||
if (bnfInnb) {
|
||||
settingsUrl += `?bnfInnb=${bnfInnb}`;
|
||||
}
|
||||
|
||||
// 설정 페이지로 이동
|
||||
window.location.href = settingsUrl;
|
||||
}
|
||||
|
||||
function showRestartConfirmModal() {
|
||||
openModal('modal-3');
|
||||
}
|
||||
|
||||
function loadProgressModalData() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/selectProgressModalData',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: 81 }),
|
||||
beforeSend: function() {
|
||||
showLoadingIndicator();
|
||||
},
|
||||
success: function(response) {
|
||||
let result = JSON.parse(response.resBody.result);
|
||||
if (result.success === true) {
|
||||
updateProgressModal(result);
|
||||
openModal('modal-1');
|
||||
} else {
|
||||
showToast(result.error || '데이터를 불러오는 데 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error fetching modal data:', error);
|
||||
showToast('서버와의 통신 중 오류가 발생했습니다.');
|
||||
},
|
||||
complete: function() {
|
||||
hideLoadingIndicator();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateProgressModal(data) {
|
||||
$('#currentStep').text(data.currentStep + '단계');
|
||||
$('#progressBar').css('width', data.progressPercent + '%');
|
||||
$('#giftTitle').text(data.giftTitle);
|
||||
$('#giftDescription').text(data.giftDescription);
|
||||
loadImage('giftImage', data.giftImageUrl, $('#giftImage'));
|
||||
$('#importantNotice').html(data.importantNotice);
|
||||
|
||||
// 진행 단계에 따라 클래스 추가
|
||||
$('.gameStatusBar span').removeClass('on');
|
||||
for (let i = 1; i <= data.currentStep; i++) {
|
||||
$(`.gameStatusBar .step0${i}`).addClass('on');
|
||||
}
|
||||
|
||||
// 5단계(완성)일 경우 'last' 클래스에도 'on' 추가
|
||||
if (data.currentStep === 5) {
|
||||
$('.gameStatusBar .last').addClass('on');
|
||||
}
|
||||
|
||||
// **추가된 부분: '새로 시작하기' 버튼 표시 여부 제어**
|
||||
if (data.progressPercent >= 100) {
|
||||
$('#newStartButtonContainer').show();
|
||||
} else {
|
||||
$('#newStartButtonContainer').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function loadImage(imageType, imagePath, $img) {
|
||||
if ($img.length && imagePath) {
|
||||
var fullImagePath = '/sopmal/bnft/image?path=' + encodeURIComponent(uploadDirs + imagePath);
|
||||
$img.attr('src', fullImagePath);
|
||||
console.log(`${imageType} image loaded successfully:`, fullImagePath);
|
||||
} else {
|
||||
console.warn(`Image element not found for ${imageType} or imagePath is empty`);
|
||||
}
|
||||
}
|
||||
|
||||
function resizeModal(modal) {
|
||||
const modalContent = modal.querySelector('.microModal__container');
|
||||
const modalBody = modal.querySelector('.microModal__body');
|
||||
const modalTop = modal.querySelector('.microModal__top');
|
||||
const modalContentArea = modal.querySelector('.microModal__content');
|
||||
const viewportHeight = window.innerHeight;
|
||||
const desiredHeight = viewportHeight * 0.9;
|
||||
|
||||
modalContent.style.height = `${desiredHeight}px`;
|
||||
modalContent.style.maxHeight = `${desiredHeight}px`;
|
||||
modalContent.style.width = '100%';
|
||||
modalContent.style.maxWidth = '100%';
|
||||
modalContent.style.margin = '0';
|
||||
modalContent.style.padding = '0';
|
||||
|
||||
modalBody.style.height = '100%';
|
||||
modalBody.style.padding = '0';
|
||||
|
||||
if (modalTop) {
|
||||
modalTop.style.padding = '10px';
|
||||
}
|
||||
|
||||
if (modalContentArea) {
|
||||
const topHeight = modalTop ? modalTop.offsetHeight : 0;
|
||||
modalContentArea.style.height = `calc(100% - ${topHeight}px)`;
|
||||
modalContentArea.style.overflowY = 'auto';
|
||||
modalContentArea.style.padding = '10px';
|
||||
}
|
||||
|
||||
const gameStatus = modal.querySelector('.gameStatus');
|
||||
const gameStatusBar = modal.querySelector('.gameStatusBar');
|
||||
const gameGiftInbox = modal.querySelector('.gameGiftInbox');
|
||||
|
||||
if (gameStatus) gameStatus.style.margin = '10px 0';
|
||||
if (gameStatusBar) gameStatusBar.style.margin = '10px 0';
|
||||
if (gameGiftInbox) gameGiftInbox.style.margin = '10px 0';
|
||||
}
|
||||
|
||||
function showLoadingIndicator() {
|
||||
$('#clipButton').text('로딩 중...').prop('disabled', true);
|
||||
}
|
||||
|
||||
function hideLoadingIndicator() {
|
||||
$('#clipButton').text('현재 진행 상태').prop('disabled', false);
|
||||
}
|
||||
|
||||
function openModal(modalId) {
|
||||
MicroModal.show(modalId, {
|
||||
onShow: function(modal) {
|
||||
if (modal.id === 'modal-1') {
|
||||
resizeModal(modal);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
document.body.style.overflow = '';
|
||||
MicroModal.close(modalId);
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
|
||||
// 풀스크린 팝업 뒤로가기 이벤트 리스너
|
||||
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 = '';
|
||||
});
|
||||
@@ -0,0 +1,168 @@
|
||||
// CpslmknIntro.js
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initializeIntro();
|
||||
initializeModal();
|
||||
openInitialModal();
|
||||
initializeButtonEvents();
|
||||
});
|
||||
|
||||
function openInitialModal() {
|
||||
// 페이지 로드 시 모달 자동 오픈
|
||||
openModal('modal-1');
|
||||
}
|
||||
|
||||
function initializeIntro() {
|
||||
var $slides = $('.gameIntroWrap');
|
||||
var $paging = $('.gamePaging');
|
||||
var currentIndex = 0;
|
||||
var slideCount = $slides.length;
|
||||
|
||||
// 페이징 생성
|
||||
for (var i = 0; i < slideCount; i++) {
|
||||
$paging.append('<span></span>');
|
||||
}
|
||||
|
||||
// 초기 슬라이드 및 페이징 설정
|
||||
showSlide(currentIndex);
|
||||
|
||||
// gameIntroPaging 클릭 이벤트
|
||||
$('.gameIntroPaging').on('click', function() {
|
||||
currentIndex = (currentIndex + 1) % slideCount;
|
||||
showSlide(currentIndex);
|
||||
});
|
||||
|
||||
// 페이징 클릭 이벤트
|
||||
$paging.on('click', 'span', function() {
|
||||
currentIndex = $(this).index();
|
||||
showSlide(currentIndex);
|
||||
});
|
||||
|
||||
function showSlide(index) {
|
||||
$slides.hide().eq(index).fadeIn();
|
||||
$paging.find('span').removeClass('active').eq(index).addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
function initializeModal() {
|
||||
MicroModal.init({
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true,
|
||||
});
|
||||
|
||||
// 풀스크린 팝업 트리거 이벤트 리스너
|
||||
$('.fullscreen-trigger').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var modalId = $(this).attr('data-micromodal-trigger');
|
||||
openModal(modalId);
|
||||
});
|
||||
|
||||
// 풀스크린 팝업 닫기 이벤트 리스너
|
||||
$('.microModal .microModal__close').on('click', function() {
|
||||
var modalId = $(this).closest('.microModal').attr('id');
|
||||
closeModal(modalId);
|
||||
});
|
||||
|
||||
// 풀스크린 팝업 뒤로가기 이벤트 리스너
|
||||
window.addEventListener('popstate', handlePopState);
|
||||
|
||||
// 페이지 로드 시 Hash 체크
|
||||
if (window.location.hash) {
|
||||
var modalId = window.location.hash.replace('#', '');
|
||||
openModal(modalId);
|
||||
}
|
||||
|
||||
// 모달 내 버튼 클릭 이벤트
|
||||
$('.microModal__btnContainer .btn').on('click', function() {
|
||||
closeModal('modal-1');
|
||||
// 여기에 캡슐 만들기 페이지로 이동하는 로직 추가
|
||||
// 예: window.location.href = 'capsule-making-page.html';
|
||||
});
|
||||
}
|
||||
|
||||
function openModal(modalId) {
|
||||
MicroModal.show(modalId, {
|
||||
onShow: function(modal) {
|
||||
if (window.location.hash !== '#' + modalId) {
|
||||
window.history.pushState({ modal: 'open' }, '', '#' + modalId);
|
||||
}
|
||||
},
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true
|
||||
});
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
document.body.style.overflow = '';
|
||||
MicroModal.close(modalId);
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
|
||||
function handlePopState(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 updateTexts() {
|
||||
const isNC = shopCode === 'NC';
|
||||
const itemName = isNC ? '초록잎' : '도토리';
|
||||
const capsuleName = isNC ? '뉴트리캡슐' : '닥터린캡슐';
|
||||
|
||||
$('.gameTop').text(`진짜 영양제를 무료로 받는 방법`);
|
||||
$('.gameIntroWrap:nth-child(2) .tit').text(`1. ${itemName}을 모아주세요.`);
|
||||
$('.gameIntroWrap:nth-child(2) p').html(`혜택 메뉴의 다양한 이벤트에 참여하면<br>${capsuleName} 만들기에 필요한<br>${itemName}을 드려요.`);
|
||||
$('.gameIntroWrap:nth-child(3) p').html(`보유한 ${itemName}을<br>실험실의 유리병에 넣어주세요.<br>모든 유리병이 가득 채워지면<br>${capsuleName}이 완성됩니다.`);
|
||||
$('.gameIntroWrap:nth-child(4) p').html(`${capsuleName}을 완성하면<br>진짜 영양제를 선물로 보내드려요.<br>그럼, 지금부터 시작해 볼까요?`);
|
||||
$('.microModal__btnContainer .btn').text(`${capsuleName} 만들러 가볼까?`);
|
||||
}
|
||||
|
||||
//이전 진행 상태 확인 함수
|
||||
function checkPreviousProgress() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/checkPreviousProgress',
|
||||
method: 'POST',
|
||||
contentType: 'application/json', // 서버에서 JSON 형식의 데이터를 기대할 때
|
||||
data: JSON.stringify({ bnfInnb: 87626 }),
|
||||
success: function(response) {
|
||||
let result = JSON.parse(response.resBody.result);
|
||||
if (result.success === true) {
|
||||
// 이전에 선택한 제품이 있으면 바로 만들기 화면으로 이동
|
||||
window.location.href = '/sopmal/bnft/makeStartCapsule?bnfInnb=' + response.bnfInnb;
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
console.error('이전 진행 상태 확인 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initializeButtonEvents() {
|
||||
const goCapsuleMakingButton = document.getElementById('goCapsuleMaking');
|
||||
if (goCapsuleMakingButton) {
|
||||
goCapsuleMakingButton.addEventListener('click', goToCapsuleMakingPage);
|
||||
}
|
||||
}
|
||||
|
||||
function goToCapsuleMakingPage() {
|
||||
window.location.href = 'http://dev.nutricore.co.kr:18310/sopmal/bnft/selectCapsule';
|
||||
}
|
||||
|
||||
// 모달 내 버튼 클릭 이벤트 업데이트
|
||||
$('.microModal__btnContainer .btn').on('click', function() {
|
||||
closeModal('modal-1');
|
||||
goToCapsuleMakingPage();
|
||||
});
|
||||
|
||||
// 페이지 로드 시 텍스트 업데이트
|
||||
$(document).ready(function() {
|
||||
// checkPreviousProgress(); // 이전 진행 상태 확인
|
||||
updateTexts();
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
// 초록잎/도토리 보유 내역 페이지로 이동하는 함수
|
||||
function goToLeafHistory() {
|
||||
// TODO: 실제 페이지 URL로 수정 필요
|
||||
window.location.href = '/sopmal/bnft/leafHistory';
|
||||
}
|
||||
|
||||
// 알림 설정 토글 함수
|
||||
function toggleNotification() {
|
||||
const $switch = $('input[role="switch"]');
|
||||
const isChecked = $switch.prop('checked');
|
||||
const agreAt = isChecked ? 'Y' : 'N';
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/capsuleAlarmAgreement',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
bnfDvCd: '050', // 캡슐만들기의 혜택 구분 코드
|
||||
bnfAgreDvCd: '010', // 알림동의 구분 코드
|
||||
agreAt: agreAt
|
||||
}),
|
||||
success: function(response) {
|
||||
let result = JSON.parse(response.resBody.result);
|
||||
if (result.success === true) {
|
||||
alert('알림 설정이 변경되었습니다.');
|
||||
} else {
|
||||
alert('알림 설정 변경에 실패했습니다.');
|
||||
// 체크박스 상태를 원래대로 되돌림
|
||||
$switch.prop('checked', !isChecked);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('서버와의 통신 중 오류가 발생했습니다.');
|
||||
// 체크박스 상태를 원래대로 되돌림
|
||||
$switch.prop('checked', !isChecked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 페이지 로드 시 실행
|
||||
$(document).ready(function() {
|
||||
const leafText = shopCode === 'NC' ? '초록잎' : '도토리';
|
||||
|
||||
// 초록잎/도토리 보유 내역 링크 텍스트 설정
|
||||
$('.productManagement li:first-child a').text(`${leafText} 보유내역`);
|
||||
|
||||
// 초록잎/도토리 보유 내역 링크에 이벤트 리스너 추가
|
||||
$('.productManagement li:first-child a').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
goToLeafHistory();
|
||||
});
|
||||
|
||||
// 알림 설정 스위치에 이벤트 리스너 추가
|
||||
$('input[role="switch"]').on('change', toggleNotification);
|
||||
|
||||
// 초기 알림 상태 설정
|
||||
$('input[role="switch"]').prop('checked', notificationStatus === 'Y');
|
||||
|
||||
// 엑스 버튼 클릭 이벤트 리스너
|
||||
$('.header__toBack__btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.history.back();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,201 @@
|
||||
// Discshar.js
|
||||
|
||||
const Discshar = (function() {
|
||||
let $slider, $slides, slideWidth, currentSlide, totalSlides, slideInterval, autoSlideTimeout;
|
||||
|
||||
function init() {
|
||||
initSlider();
|
||||
bindEvents();
|
||||
loadImages();
|
||||
}
|
||||
|
||||
function initSlider() {
|
||||
$slider = $('.discountSlider ul');
|
||||
$slides = $('.discountSlider li');
|
||||
slideWidth = $slides.outerWidth() + parseInt($slides.css('margin-right'));
|
||||
currentSlide = 0;
|
||||
totalSlides = $slides.length;
|
||||
slideInterval = 3000; // 슬라이드 간격 (밀리초)
|
||||
|
||||
// 첫 번째 및 마지막 슬라이드 복제
|
||||
$slides.first().before($slides.last().clone());
|
||||
$slides.last().after($slides.first().clone());
|
||||
|
||||
// 복제된 슬라이드를 포함하여 총 슬라이드 수 업데이트
|
||||
totalSlides += 2;
|
||||
|
||||
// 모든 <li> 항목의 총 너비로 .discountSlider ul의 너비 설정
|
||||
$slider.width(totalSlides * slideWidth);
|
||||
|
||||
// 첫 번째 원본 슬라이드로 초기 위치 설정
|
||||
$slider.css('margin-left', -slideWidth);
|
||||
|
||||
startAutoSlide();
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
$slider.on('mouseenter', stopAutoSlide)
|
||||
.on('mouseleave', startAutoSlide)
|
||||
.on('mousedown touchstart', startDrag)
|
||||
.on('mousemove touchmove', drag)
|
||||
.on('mouseup touchend', endDrag);
|
||||
|
||||
$(document).on('mouseup touchend', endDrag);
|
||||
|
||||
// 데스크톱 브라우저에서 이미지 드래그 방지
|
||||
$('.discountSlider img').on('dragstart', function(event) { event.preventDefault(); });
|
||||
}
|
||||
|
||||
function startAutoSlide() {
|
||||
autoSlideTimeout = setInterval(nextSlide, slideInterval);
|
||||
}
|
||||
|
||||
function stopAutoSlide() {
|
||||
clearInterval(autoSlideTimeout);
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
currentSlide++;
|
||||
moveSlide();
|
||||
}
|
||||
|
||||
function moveSlide() {
|
||||
$slider.animate({'margin-left': -currentSlide * slideWidth}, 500, function() {
|
||||
if (currentSlide >= totalSlides - 1) {
|
||||
currentSlide = 1;
|
||||
$slider.css('margin-left', -slideWidth);
|
||||
} else if (currentSlide <= 0) {
|
||||
currentSlide = totalSlides - 2;
|
||||
$slider.css('margin-left', -currentSlide * slideWidth);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let isDragging = false;
|
||||
let startPos = 0;
|
||||
let currentPos = 0;
|
||||
|
||||
function startDrag(e) {
|
||||
isDragging = true;
|
||||
startPos = e.pageX || e.originalEvent.touches[0].pageX;
|
||||
currentPos = $slider.css('margin-left');
|
||||
stopAutoSlide();
|
||||
}
|
||||
|
||||
function drag(e) {
|
||||
if (!isDragging) return;
|
||||
let currentMousePos = e.pageX || e.originalEvent.touches[0].pageX;
|
||||
let diff = currentMousePos - startPos;
|
||||
$slider.css('margin-left', parseInt(currentPos) + diff);
|
||||
}
|
||||
|
||||
function endDrag(e) {
|
||||
if (!isDragging) return;
|
||||
isDragging = false;
|
||||
let endPos = e.pageX || e.originalEvent.changedTouches[0].pageX;
|
||||
let diff = endPos - startPos;
|
||||
if (Math.abs(diff) > 50) {
|
||||
currentSlide += (diff > 0) ? -1 : 1;
|
||||
moveSlide();
|
||||
} else {
|
||||
$slider.animate({'margin-left': currentPos}, 200);
|
||||
}
|
||||
startAutoSlide();
|
||||
}
|
||||
|
||||
function loadImages() {
|
||||
console.log('Starting to load images');
|
||||
loadImage('representative', screenInfo.representativeImagePath, $('.discountThumnail img'));
|
||||
|
||||
screenInfo.productImages.forEach((imagePath, index) => {
|
||||
loadImage(`product-${index}`, imagePath, $(`.discountList li:eq(${index}) .thumnail img`));
|
||||
});
|
||||
}
|
||||
|
||||
function loadImage(imageType, imagePath, $img) {
|
||||
if (!imagePath) {
|
||||
console.warn(`Image path for ${imageType} is not available`);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($img.length) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/image',
|
||||
method: 'GET',
|
||||
data: { path: imagePath },
|
||||
xhrFields: { responseType: 'blob' },
|
||||
success: function(data) {
|
||||
const imageUrl = URL.createObjectURL(data);
|
||||
$img.attr('src', imageUrl);
|
||||
console.log(`${imageType} image loaded successfully`);
|
||||
},
|
||||
error: function() {
|
||||
console.error(`Failed to load ${imageType} image`);
|
||||
$img.attr('src', '/path/to/fallback-image.jpg');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(`Image element not found for ${imageType}`);
|
||||
}
|
||||
}
|
||||
|
||||
function copyLink(bnfInnb) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/copyDiscsharLink',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: bnfInnb }),
|
||||
success: function(response) {
|
||||
if (response.success && response.links && response.links.length > 0) {
|
||||
const link = response.links[0];
|
||||
navigator.clipboard.writeText(link.uniqueUrl)
|
||||
.then(() => {
|
||||
const validDate = new Date(link.validDt);
|
||||
const formattedDate = validDate.toISOString().split('T')[0];
|
||||
$('#linkExpiryDate').text(formattedDate);
|
||||
MicroModal.show('modal-1');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('링크 복사 실패:', err.message);
|
||||
alert('링크 복사에 실패했습니다.');
|
||||
});
|
||||
} else {
|
||||
alert('유효한 링크 정보가 없습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('서버 통신 오류:', error);
|
||||
alert('서버 통신 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showShareResult() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/checkDiscsharResult',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({}),
|
||||
success: function(response) {
|
||||
if (response.hasPurchase) {
|
||||
MicroModal.show('modal-3');
|
||||
} else {
|
||||
MicroModal.show('modal-2');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('공유 결과를 확인하는데 실패했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
copyLink: copyLink,
|
||||
showShareResult: showShareResult
|
||||
};
|
||||
})();
|
||||
|
||||
$(document).ready(function() {
|
||||
Discshar.init();
|
||||
});
|
||||
@@ -0,0 +1,137 @@
|
||||
const EventView = (function() {
|
||||
let timer;
|
||||
let remainingTime;
|
||||
let currentEventId;
|
||||
let startTime;
|
||||
let eventWindow; // 열린 이벤트 창
|
||||
let eventCheckInterval; // 자식 창 상태 확인 타이머
|
||||
let currentMlgRwdAmt; // 현재 이벤트의 마일리지 보상 금액
|
||||
|
||||
// 이벤트 시작 함수
|
||||
function startEventView(bnfInnb, linkUrl, seconds, mlgRwdAmt) {
|
||||
|
||||
// 먼저 이벤트의 적립 상태를 확인
|
||||
if (isEventAccumulated(bnfInnb)) {
|
||||
alert('이미 적립이 완료된 이벤트입니다.');
|
||||
window.open(linkUrl, 'eventView', 'width=800,height=600');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/startEventView',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: bnfInnb }),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
currentEventId = bnfInnb;
|
||||
remainingTime = seconds;
|
||||
startTime = new Date().getTime();
|
||||
currentMlgRwdAmt = mlgRwdAmt; // 현재 마일리지 값 저장
|
||||
|
||||
// 이벤트 창 열기
|
||||
eventWindow = window.open(linkUrl, 'eventView', 'width=800,height=600');
|
||||
$('.topupPoint').show(); // 초 카운트 표시
|
||||
startTimer();
|
||||
|
||||
// 자식 창 상태 주기적으로 확인
|
||||
eventCheckInterval = setInterval(function() {
|
||||
if (eventWindow.closed) {
|
||||
stopTimer();
|
||||
$('.topupPoint').hide(); // 초 카운트 숨기기
|
||||
clearInterval(eventCheckInterval);
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
alert(response.message || '이벤트 시작에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('이벤트 시작 요청 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 타이머 시작 함수
|
||||
function startTimer() {
|
||||
updateTimerDisplay();
|
||||
|
||||
clearInterval(timer); // 기존 타이머 제거
|
||||
timer = setInterval(function() {
|
||||
remainingTime--;
|
||||
updateTimerDisplay();
|
||||
|
||||
if (remainingTime <= 0) {
|
||||
clearInterval(timer);
|
||||
completeMileageAccumulation();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// 타이머 디스플레이 업데이트 함수
|
||||
function updateTimerDisplay() {
|
||||
$('#countdown').text(remainingTime);
|
||||
}
|
||||
|
||||
// 마일리지 적립 완료 처리 함수
|
||||
function completeMileageAccumulation() {
|
||||
let endTime = new Date().getTime();
|
||||
let duration = (endTime - startTime) / 1000;
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/completeMileageAccumulation',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: currentEventId,
|
||||
duration: duration,
|
||||
mlgRwdAmt: currentMlgRwdAmt // 마일리지 값을 서버로 전송
|
||||
}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
alert('마일리지가 적립되었습니다!');
|
||||
updateEventStatus(currentEventId);
|
||||
$('.topupPoint').hide(); // 초 카운트 숨기기
|
||||
} else {
|
||||
alert(response.message || '마일리지 적립에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error:', error);
|
||||
alert('마일리지 적립 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 타이머 멈추기 함수
|
||||
function stopTimer() {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
if (eventCheckInterval) {
|
||||
clearInterval(eventCheckInterval);
|
||||
}
|
||||
}
|
||||
|
||||
function isEventAccumulated(bnfInnb) {
|
||||
return $(`.li_mile[data-bnf-innb="${bnfInnb}"]`).hasClass('on');
|
||||
}
|
||||
|
||||
function updateEventStatus(bnfInnb) {
|
||||
const mileElement = $(`.li_mile[data-bnf-innb="${bnfInnb}"]`);
|
||||
mileElement.addClass('on').find('span').text('적립완료');
|
||||
}
|
||||
|
||||
return {
|
||||
start: startEventView,
|
||||
stop: stopTimer
|
||||
};
|
||||
})();
|
||||
|
||||
// 창이 닫힐 때 타이머 멈추기
|
||||
$(window).on('beforeunload', function() {
|
||||
EventView.stop();
|
||||
});
|
||||
|
||||
// 디버깅을 위한 콘솔 로그 추가
|
||||
console.log('EventView script loaded');
|
||||
@@ -0,0 +1,187 @@
|
||||
$(document).ready(function() {
|
||||
// 관심분야 목록 렌더링 함수
|
||||
function renderInterestList() {
|
||||
const $favoriteList = $('.favoriteList');
|
||||
$favoriteList.empty(); // 기존 목록 초기화
|
||||
// 각 관심분야에 대해 리스트 아이템 생성
|
||||
interestAreas.forEach(function(interest) {
|
||||
const $li = $('<li>');
|
||||
const $a = $('<a>').attr('href', '#');
|
||||
const $imgP = $('<p>').addClass('img');
|
||||
const $img = $('<img>')
|
||||
.attr('alt', interest.name)
|
||||
.attr('data-interest-id', interest.id);
|
||||
const $titleP = $('<p>').addClass('tit').text(interest.name);
|
||||
$imgP.append($img);
|
||||
$a.append($imgP).append($titleP);
|
||||
$li.append($a);
|
||||
$favoriteList.append($li);
|
||||
// 이미지 로드
|
||||
loadImage(interest.id, interest.beforeImagePath);
|
||||
});
|
||||
// 클릭 이벤트 리스너 추가
|
||||
$('.favoriteList li a').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$(this).closest('li').toggleClass('on');
|
||||
});
|
||||
|
||||
// 사용자 관심분야 조회 및 UI 업데이트
|
||||
getUserInterests();
|
||||
}
|
||||
|
||||
// 사용자 관심분야 조회 함수 추가
|
||||
function getUserInterests() {
|
||||
const bnfInnb = $('#bnfInnb').val();
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/selectUserInterests',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: bnfInnb }),
|
||||
success: function(response) {
|
||||
if (response && response.interestAreas) {
|
||||
updateUIWithUserInterests(response.interestAreas);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Failed to fetch user interests:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// UI 업데이트 함수 추가
|
||||
function updateUIWithUserInterests(userInterests) {
|
||||
$('.favoriteList li').removeClass('on');
|
||||
userInterests.forEach(function(interest) {
|
||||
$('.favoriteList li img[data-interest-id="' + interest.bnfIntrstInnb + '"]')
|
||||
.closest('li')
|
||||
.addClass('on');
|
||||
});
|
||||
}
|
||||
|
||||
// 이미지 로드 함수
|
||||
function loadImage(interestId, imagePath) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/image',
|
||||
method: 'GET',
|
||||
data: { path: imagePath },
|
||||
xhrFields: {
|
||||
responseType: 'blob'
|
||||
},
|
||||
success: function(data) {
|
||||
var $img = $('img[data-interest-id="' + interestId + '"]');
|
||||
var imageUrl = URL.createObjectURL(data);
|
||||
$img.attr('src', imageUrl);
|
||||
},
|
||||
error: function() {
|
||||
console.error('Failed to load image for interest:', interestId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 마일리지 상태 업데이트 함수 추가
|
||||
function updateMileageStatus() {
|
||||
const bnfInnb = $('#bnfInnb').val();
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/selectUserInterestSaveStatus',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: bnfInnb }),
|
||||
success: function(response) {
|
||||
if (response.savedYn === 'Y') {
|
||||
if (response.mileageAccumulatedYn === 'Y') {
|
||||
$('.topupPoint.noSticky span').html('마일리지 ' + response.mlgRwdAmt + '원 적립완료');
|
||||
} else {
|
||||
$('.topupPoint.noSticky span').html('마일리지 ' + response.mlgRwdAmt + '원 적립완료');
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Failed to get user interest save status:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 초기 관심분야 목록 렌더링
|
||||
renderInterestList();
|
||||
|
||||
// 초기 마일리지 상태 업데이트
|
||||
updateMileageStatus();
|
||||
|
||||
// 저장 버튼 초기 상태 설정
|
||||
$('#saveBtn').prop('disabled', true);
|
||||
|
||||
// 체크박스 상태 변경 이벤트 핸들러
|
||||
$('#agreementCheckbox').on('change', function() {
|
||||
$('#saveBtn').prop('disabled', !this.checked);
|
||||
});
|
||||
|
||||
// 저장 버튼 클릭 이벤트 핸들러
|
||||
$('#saveBtn').on('click', function() {
|
||||
var agreementChecked = $('#agreementCheckbox').is(':checked');
|
||||
|
||||
// 동의 체크박스 확인
|
||||
if (!agreementChecked) {
|
||||
showToast('관심분야 정보받기에 동의해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 선택된 관심분야 수집
|
||||
var selectedInterests = $('.favoriteList li.on').map(function() {
|
||||
return {
|
||||
bnfIntrstInnb: $(this).find('img').data('interest-id'),
|
||||
selected: true
|
||||
};
|
||||
}).get();
|
||||
|
||||
// 최소 1개 이상의 관심분야 선택 확인
|
||||
if (selectedInterests.length === 0) {
|
||||
showToast('최소 1개 이상의 관심분야를 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
const bnfInnb = $('#bnfInnb').val();
|
||||
|
||||
// 서버로 전송할 데이터 준비
|
||||
var data = {
|
||||
bnfInnb: bnfInnb,
|
||||
interestAreas: selectedInterests,
|
||||
agreementFlag: agreementChecked
|
||||
};
|
||||
|
||||
console.log(data);
|
||||
// AJAX 요청
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/saveUserInterests',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(data),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
showToast(response.message);
|
||||
if (response.mileageAccumulated) {
|
||||
showToast('마일리지가 적립되었습니다.');
|
||||
updateMileageStatus(); // 마일리지 상태 업데이트
|
||||
}
|
||||
getUserInterests(); // 사용자 관심분야 재조회
|
||||
} else {
|
||||
showToast('저장 중 오류가 발생했습니다: ' + response.message);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
showToast('서버와의 통신 중 오류가 발생했습니다.');
|
||||
console.error('Error:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 토스트 메시지 표시 함수
|
||||
function showToast(message) {
|
||||
var $toastPop = $('#toastPop');
|
||||
$toastPop.find('.txt').text(message);
|
||||
$toastPop.addClass('show');
|
||||
// 2초 후 토스트 메시지 숨김
|
||||
setTimeout(function() {
|
||||
$toastPop.removeClass('show');
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,921 @@
|
||||
var Intakchl = (function() {
|
||||
"use strict";
|
||||
|
||||
const baseUrl = '/sopmal/bnft';
|
||||
let bnfInnb;
|
||||
let screenInfo;
|
||||
let productList;
|
||||
let selectedProducts = [];
|
||||
const calendarDays = document.getElementById('calendarDays');
|
||||
const currentMonthElement = document.getElementById('currentMonth');
|
||||
const prevWeekButton = document.getElementById('prevWeek');
|
||||
const nextWeekButton = document.getElementById('nextWeek');
|
||||
|
||||
let count = 1;
|
||||
let currentDate = new Date();
|
||||
let focusedDate = null;
|
||||
const dayNames = ['일', '월', '화', '수', '목', '금', '토'];
|
||||
|
||||
|
||||
|
||||
function init(info, products) {
|
||||
bnfInnb = getUrlParameter('bnfInnb');
|
||||
count = info.dailyIntakeCount || 1;
|
||||
screenInfo = info || {};
|
||||
productList = products || [];
|
||||
loadSelectedProducts();
|
||||
initModal();
|
||||
bindEvents();
|
||||
updateDisplay();
|
||||
showTab('purchased-tab');
|
||||
initEventListeners();
|
||||
// 현재 페이지가 섭취 챌린지 메인 페이지인 경우에만 이벤트 리스너 추가
|
||||
if (isIntakeChallengeMainPage()) {
|
||||
addCalendarEventListeners();
|
||||
loadDailyIntakeData(formatDate(currentDate));
|
||||
loadIntakeChallengeDashboard(); // 새로운 함수 호출 추가
|
||||
updateCalendar();
|
||||
} else if (isIntakchlDailyRecordMainPage) {
|
||||
loadStatsDateClasses();
|
||||
loadCurrentChallengeProducts();
|
||||
}
|
||||
|
||||
if (window.location.hash) {
|
||||
var modalId = window.location.hash.replace('#', '');
|
||||
openModal({ preventDefault: function(){}, target: $('[data-micromodal-trigger="' + modalId + '"]')[0] });
|
||||
}
|
||||
|
||||
// MicroModal 초기화
|
||||
MicroModal.init({
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true,
|
||||
});
|
||||
}
|
||||
|
||||
function initModal() {
|
||||
MicroModal.init({
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true,
|
||||
});
|
||||
}
|
||||
|
||||
function navigateToAddProduct() {
|
||||
const url = `${baseUrl}/intakchlMain?bnfInnb=${bnfInnb}`;
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
function getUrlParameter(name) {
|
||||
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
|
||||
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
|
||||
var results = regex.exec(location.search);
|
||||
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||
}
|
||||
|
||||
function isIntakeChallengeMainPage() {
|
||||
// 현재 페이지가 섭취 챌린지 메인 페이지인지 확인하는 로직
|
||||
// 예: URL 체크, 특정 요소의 존재 여부 확인 등
|
||||
return window.location.pathname.includes('/intakchlDailyRecordMain');
|
||||
}
|
||||
|
||||
function isIntakchlDailyRecordMainPage() {
|
||||
// 현재 페이지가 섭취 통계 페이지인지 확인하는 로직
|
||||
// 예: URL 체크, 특정 요소의 존재 여부 확인 등
|
||||
return window.location.pathname.includes('/intakchlMileageSummary');
|
||||
}
|
||||
|
||||
function isintakchlChallengeSettingsPage() {
|
||||
// 현재 페이지가 섭취 통계 페이지인지 확인하는 로직
|
||||
// 예: URL 체크, 특정 요소의 존재 여부 확인 등
|
||||
return window.location.pathname.includes('/intakchlChallengeSettings');
|
||||
}
|
||||
|
||||
function goToProductDetail(bnfNtkInnb) {
|
||||
window.location.href = baseUrl + '/intakchlProductDetail?bnfNtkInnb=' + bnfNtkInnb;
|
||||
}
|
||||
|
||||
function goToAddProduct() {
|
||||
window.location.href = baseUrl + '/intakchlMain?bnfInnb=' + bnfInnb;
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
$('#addToChallengeBtn').off('click');
|
||||
|
||||
$('.headerTab__item').on('click', function() {
|
||||
showTab($(this).attr('id'));
|
||||
});
|
||||
|
||||
$('#addToChallengeBtn').on('click', addToChallenge);
|
||||
$('#continueAdding').on('click', continueAdding);
|
||||
$('#startChallenge').on('click', startChallenge);
|
||||
|
||||
$('.challenge_checklist input[type="checkbox"]').on('change', function() {
|
||||
updateSelectedProductCount();
|
||||
});
|
||||
|
||||
$('.btn_add_challenge').on('click', function() {
|
||||
window.location.href = baseUrl + '/intakeChallengeAdd?bnfInnb=' + screenInfo.bnfInnb;
|
||||
});
|
||||
|
||||
$('#prevWeek').on('click', function() {
|
||||
updateCalendar(-7);
|
||||
});
|
||||
|
||||
$('#nextWeek').on('click', function() {
|
||||
updateCalendar(7);
|
||||
});
|
||||
|
||||
$(document).on('click', '.calendar-days .day', function() {
|
||||
handleDateClick(new Date($(this).data('date')));
|
||||
});
|
||||
|
||||
// 섭취 버튼 클릭 이벤트 추가
|
||||
$(document).on('click', '.drugCheck span', function() {
|
||||
updateIntakeStatus($(this));
|
||||
});
|
||||
|
||||
$('#save_toast').off('click').on('click', updateDailyIntakeAndMemo);
|
||||
|
||||
$('.btn_add_challenge').on('click', navigateToAddProduct);
|
||||
|
||||
$('.microModal__btn-primary').on('click', deleteProduct);
|
||||
|
||||
// 섭취 카운트 관련 이벤트
|
||||
$('#decrease').on('click', decreaseCount);
|
||||
$('#increase').on('click', increaseCount);
|
||||
|
||||
// 모달 관련 이벤트
|
||||
$('.fullscreen-trigger').on('click', openModal);
|
||||
$('.microModal .microModal__close').on('click', closeModal);
|
||||
window.addEventListener('popstate', handlePopState);
|
||||
|
||||
$('.header__toBack__btn').on('click', function() {
|
||||
history.back();
|
||||
});
|
||||
$('#modal-1 .microModal__btn-primary').on('click', deleteProduct);
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('statsButton').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = '/sopmal/bnft/intakchlMileageSummary';
|
||||
});
|
||||
|
||||
document.getElementById('settingsButton').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = '/sopmal/bnft/intakchlChallengeSettings';
|
||||
});
|
||||
|
||||
function decreaseCount() {
|
||||
if (count > 1) {
|
||||
count--;
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
function increaseCount() {
|
||||
if (count < 10) {
|
||||
count++;
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
function updateDisplay() {
|
||||
$('#count').text(count);
|
||||
$('#decrease').prop('disabled', count === 1);
|
||||
$('#increase').prop('disabled', count === 10);
|
||||
}
|
||||
|
||||
function openModal(e) {
|
||||
e.preventDefault();
|
||||
var modalId = $(this).attr('data-micromodal-trigger');
|
||||
MicroModal.show(modalId, {
|
||||
onShow: function (modal) {
|
||||
if (window.location.hash !== '#' + modalId) {
|
||||
window.history.pushState({ modal: 'open' }, '', '#' + modalId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
var modalId = $(this).closest('.microModal').attr('id');
|
||||
document.body.style.overflow = '';
|
||||
MicroModal.close(modalId);
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
|
||||
function handlePopState(event) {
|
||||
var modalId = window.location.hash.replace('#', '');
|
||||
if (modalId) {
|
||||
closeModal();
|
||||
} else {
|
||||
$('.microModal').each(function () {
|
||||
MicroModal.close($(this).attr('id'));
|
||||
});
|
||||
}
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
function deleteProduct() {
|
||||
const bnfNtkInnb = $('#bnfNtkInnb').val();
|
||||
$.ajax({
|
||||
url: baseUrl + '/deleteIntakeChallengeProduct',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfNtkInnb: bnfNtkInnb,
|
||||
mbrInnb: getMbrInnb(),
|
||||
mbrDvCd: getMbrDvCd()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
alert('제품이 삭제되었습니다.');
|
||||
window.location.href = baseUrl + '/intakchlMain?bnfInnb=' + bnfInnb;
|
||||
} else {
|
||||
alert('삭제에 실패했습니다: ' + result.message);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('서버 오류가 발생했습니다. 다시 시도해 주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateDailyIntakeAndMemo() {
|
||||
const productData = {
|
||||
bnfNtkInnb: $('#bnfNtkInnb').val(),
|
||||
intakeStatus: $('input[name="intakeStatus"]:checked').val(),
|
||||
dailyIntakeCount: count,
|
||||
memo: $('.white_textarea').val()
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: baseUrl + '/updateDailyIntakeAndMemo',
|
||||
method: 'POST',
|
||||
data: JSON.stringify(productData),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
showToast(result.message);
|
||||
} else {
|
||||
alert(result.message);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('서버 오류가 발생했습니다. 다시 시도해 주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const $toastPop = $('#toastPop');
|
||||
$toastPop.find('p').text(message);
|
||||
$toastPop.addClass('show');
|
||||
|
||||
setTimeout(function() {
|
||||
$toastPop.removeClass('show');
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function updateIntakeStatus(element) {
|
||||
const productContainer = element.closest('.challengeProduct');
|
||||
const bnfNtkInnb = productContainer.data('bnf-ntk-innb');
|
||||
const goodsInnb = productContainer.data('goods-innb');
|
||||
const targetIntakeCount = productContainer.data('target-intake-count');
|
||||
const currentIntakeCount = productContainer.find('.drug_on').length;
|
||||
const newStatus = element.hasClass('drug_off') ? 'Y' : 'N';
|
||||
|
||||
// 현재 선택된 날짜 가져오기
|
||||
const selectedDate = formatDate(currentDate);
|
||||
|
||||
// 섭취 완료 시 목표 섭취 횟수를 초과하는지 확인
|
||||
if (newStatus === 'Y' && currentIntakeCount >= targetIntakeCount) {
|
||||
alert('오늘의 목표 섭취 횟수를 이미 달성했습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: baseUrl + '/updateIntakeStatus',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
bnfNtkInnb: bnfNtkInnb,
|
||||
intakeStatus: newStatus,
|
||||
goodsInnb: goodsInnb,
|
||||
currentIntakeCount: currentIntakeCount,
|
||||
targetIntakeCount: targetIntakeCount,
|
||||
mbrInnb: getMbrInnb(),
|
||||
mbrDvCd: getMbrDvCd(),
|
||||
selectedDate: selectedDate // 추가된 부분
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
const updatedProduct = result.updatedProductInfo.find(p => p.goodsInnb === goodsInnb);
|
||||
if (updatedProduct) {
|
||||
updateProductUI(productContainer, updatedProduct);
|
||||
}
|
||||
updateTotalIntakeUI(result.updatedTotalInfo);
|
||||
checkAndAwardMileage(); // 섭취 상태 업데이트 후 마일리지 적립 확인
|
||||
} else {
|
||||
alert(result.message || '상태 업데이트에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('AJAX 요청 실패:', error);
|
||||
alert('서버 오류가 발생했습니다. 다시 시도해 주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function checkAndAwardMileage() {
|
||||
$.ajax({
|
||||
url: baseUrl + '/awardIntakeChallengesMileage',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
mbrInnb: getMbrInnb(),
|
||||
mbrDvCd: getMbrDvCd()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
showMileageAwardMessage(result.awardedAmount);
|
||||
} else if (result.message !== "일일 섭취 목표를 달성하지 못했습니다.") {
|
||||
// 목표 미달성이 아닌 다른 이유로 실패한 경우에만 메시지 표시
|
||||
alert(result.message);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('마일리지 지급 요청 실패:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showMileageAwardMessage(amount) {
|
||||
$('.topupPoint span').html(`<i class="ico_mile"></i><b>마일리지 ${amount}원</b> 적립완료!`);
|
||||
}
|
||||
|
||||
function updateMileageMessage(percentage) {
|
||||
if (percentage < 100) {
|
||||
$('.topupPoint span').html(`오늘의 섭취기록 100% 도달시<i class="ico_mile"></i><b>마일리지 10원</b>적립`);
|
||||
}
|
||||
// 100% 도달 시 메시지는 showMileageAwardMessage 함수에서 처리됩니다.
|
||||
}
|
||||
|
||||
// 개별 제품 UI 업데이트 함수
|
||||
function updateProductUI(productContainer, updatedInfo) {
|
||||
const drugCheckContainer = productContainer.find('.drugCheck');
|
||||
drugCheckContainer.empty();
|
||||
|
||||
for (let i = 0; i < updatedInfo.targetIntakeCount; i++) {
|
||||
const className = i < updatedInfo.dailyIntakeCount ? 'drug_on' : 'drug_off';
|
||||
const text = i < updatedInfo.dailyIntakeCount ? '섭취완료' : '섭취미완료';
|
||||
drugCheckContainer.append(`<span class="${className}">${text}</span>`);
|
||||
}
|
||||
|
||||
productContainer.data('target-intake-count', updatedInfo.targetIntakeCount);
|
||||
productContainer.find('.target-count').text(updatedInfo.targetIntakeCount);
|
||||
}
|
||||
|
||||
// 전체 섭취 현황 UI 업데이트 함수
|
||||
function updateTotalIntakeUI(totalInfo) {
|
||||
updateProgressBar(totalInfo.totalDailyIntakeRatio);
|
||||
updateMileageMessage(totalInfo.totalDailyIntakeRatio);
|
||||
}
|
||||
|
||||
function showTab(tabId) {
|
||||
$('.headerTab__item').removeClass('active');
|
||||
$('#' + tabId).addClass('active');
|
||||
$('.challenge_checklist').hide();
|
||||
$('.challenge_checklist.' + tabId.replace('-tab', '')).show();
|
||||
}
|
||||
|
||||
function addToChallenge() {
|
||||
var newSelectedProducts = $('.challenge_checklist input[type="checkbox"]:checked').map(function() {
|
||||
return {
|
||||
goodsInnb: $(this).val(),
|
||||
sopmalCd: "NC"
|
||||
};
|
||||
}).get();
|
||||
|
||||
if (newSelectedProducts.length === 0) {
|
||||
alert('선택한 제품이 없습니다. 제품을 선택해 주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
selectedProducts = selectedProducts.concat(newSelectedProducts);
|
||||
saveSelectedProducts();
|
||||
|
||||
$.ajax({
|
||||
url: baseUrl + '/addSelectedProducts',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: screenInfo.bnfInnb,
|
||||
products: newSelectedProducts
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
MicroModal.show('modal-1');
|
||||
} else {
|
||||
alert(response.message || '제품 추가에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('서버 오류가 발생했습니다. 다시 시도해 주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function continueAdding() {
|
||||
MicroModal.close('modal-1');
|
||||
$('.challenge_checklist input[type="checkbox"]').prop('checked', false);
|
||||
updateSelectedProductCount();
|
||||
}
|
||||
|
||||
function startChallenge() {
|
||||
window.location.href = baseUrl + '/IntakchlDailyRecordMain?bnfInnb=' + screenInfo.bnfInnb;
|
||||
}
|
||||
|
||||
function updateSelectedProductCount() {
|
||||
var count = $('.challenge_checklist input[type="checkbox"]:checked').length;
|
||||
$('#selectedCount').text(count);
|
||||
}
|
||||
|
||||
function saveSelectedProducts() {
|
||||
localStorage.setItem('selectedProducts', JSON.stringify(selectedProducts));
|
||||
}
|
||||
|
||||
function loadSelectedProducts() {
|
||||
var storedProducts = localStorage.getItem('selectedProducts');
|
||||
if (storedProducts) {
|
||||
selectedProducts = JSON.parse(storedProducts);
|
||||
selectedProducts.forEach(function(productId) {
|
||||
$('.challenge_checklist input[value="' + productId.goodsInnb + '"]').prop('checked', true);
|
||||
});
|
||||
updateSelectedProductCount();
|
||||
}
|
||||
}
|
||||
|
||||
//캘린더 스크립트
|
||||
function updateCalendar() {
|
||||
calendarDays.innerHTML = '';
|
||||
currentMonthElement.textContent = `${currentDate.getFullYear()}년 ${currentDate.getMonth() + 1}월`;
|
||||
|
||||
for (let i = -3; i <= 3; i++) {
|
||||
const date = new Date(currentDate);
|
||||
date.setDate(currentDate.getDate() + i);
|
||||
|
||||
const dayElement = document.createElement('div');
|
||||
dayElement.classList.add('day');
|
||||
if (i === 0) dayElement.classList.add('center');
|
||||
if (date.toDateString() === new Date().toDateString()) {
|
||||
dayElement.classList.add('today');
|
||||
}
|
||||
if (focusedDate && date.toDateString() === focusedDate.toDateString()) {
|
||||
dayElement.classList.add('focused');
|
||||
}
|
||||
|
||||
const dayNameElement = document.createElement('div');
|
||||
dayNameElement.classList.add('day-name');
|
||||
dayNameElement.textContent = dayNames[date.getDay()];
|
||||
|
||||
const dayNumberElement = document.createElement('div');
|
||||
dayNumberElement.classList.add('day-number');
|
||||
dayNumberElement.textContent = date.getDate();
|
||||
|
||||
dayElement.appendChild(dayNameElement);
|
||||
dayElement.appendChild(dayNumberElement);
|
||||
dayElement.addEventListener('click', () => handleDateClick(date));
|
||||
calendarDays.appendChild(dayElement);
|
||||
}
|
||||
}
|
||||
|
||||
function handleDateClick(date) {
|
||||
currentDate = new Date(date); // 이 줄을 추가
|
||||
focusedDate = date;
|
||||
updateCalendar();
|
||||
loadDailyIntakeData(formatDate(date));
|
||||
}
|
||||
|
||||
function loadDailyIntakeData(dateStr) {
|
||||
$.ajax({
|
||||
url: baseUrl + '/selectDailyTotalIntakeRecord',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
selectedDate: dateStr,
|
||||
mbrInnb: getMbrInnb(), // 회원 정보 추가
|
||||
mbrDvCd: getMbrDvCd() // 회원 구분 코드 추가
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
if (response.resBody && response.resBody.result) {
|
||||
var result = JSON.parse(response.resBody.result);
|
||||
if (result.dailyTotalIntakeRecord) {
|
||||
updateIntakeUI(result.dailyTotalIntakeRecord, result.dailyIntakeRecordsDetail);
|
||||
} else {
|
||||
console.error('데이터 로드 실패:', result.message);
|
||||
}
|
||||
} else {
|
||||
console.error('잘못된 응답 형식:', response);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('AJAX 요청 실패:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateIntakeUI(totalData, detailData) {
|
||||
updateProgressBar(totalData.totalDailyIntakeRatio);
|
||||
|
||||
const container = $('#challengeProductContainer');
|
||||
container.empty();
|
||||
|
||||
detailData.forEach(function(product) {
|
||||
const productElement = createProductElement(product);
|
||||
container.append(productElement);
|
||||
});
|
||||
}
|
||||
|
||||
// createProductElement 함수 수정
|
||||
function createProductElement(product) {
|
||||
const productHtml = `
|
||||
<div class="challengeProduct" data-bnf-ntk-innb="${product.bnfNtkInnb}" data-goods-innb="${product.goodsInnb}" data-target-intake-count="${product.targetIntakeCount}">
|
||||
<a href="#">
|
||||
<div class="thum"><img src="../resources/images/event/discount_thum3.png" alt="${product.goodsNm}"></div>
|
||||
<div class="cpTit">
|
||||
<p class="tit">${product.goodsNm}</p>
|
||||
<p class="dayCheck">1일 <span class="target-count">${product.targetIntakeCount}</span>회</p>
|
||||
</div>
|
||||
<div class="drugCheck">
|
||||
${createIntakeButtons(product.dailyIntakeCount, product.targetIntakeCount)}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
return $(productHtml);
|
||||
}
|
||||
|
||||
|
||||
function formatDate(date) {
|
||||
var d = new Date(date),
|
||||
month = '' + (d.getMonth() + 1),
|
||||
day = '' + d.getDate(),
|
||||
year = d.getFullYear();
|
||||
|
||||
if (month.length < 2) month = '0' + month;
|
||||
if (day.length < 2) day = '0' + day;
|
||||
|
||||
return [year, month, day].join('-');
|
||||
}
|
||||
|
||||
function createIntakeButtons(dailyIntakeCount, targetIntakeCount) {
|
||||
let buttons = '';
|
||||
for (let i = 0; i < (targetIntakeCount || 1); i++) {
|
||||
const className = i < dailyIntakeCount ? 'drug_on' : 'drug_off';
|
||||
const text = i < dailyIntakeCount ? '섭취완료' : '섭취미완료';
|
||||
buttons += `<span class="${className}">${text}</span>`;
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
|
||||
function updateProgressBar(percentage) {
|
||||
percentage = Math.round(percentage || 0);
|
||||
$('.challengeBar-container .per').css('width', percentage + '%');
|
||||
$('.challengeBar-container .per-txt').text(percentage + '%');
|
||||
updateMileageMessage(percentage);
|
||||
}
|
||||
|
||||
function addCalendarEventListeners() {
|
||||
if (prevWeekButton && nextWeekButton) {
|
||||
prevWeekButton.addEventListener('click', () => {
|
||||
currentDate.setDate(currentDate.getDate() - 7);
|
||||
updateCalendar();
|
||||
});
|
||||
|
||||
nextWeekButton.addEventListener('click', () => {
|
||||
currentDate.setDate(currentDate.getDate() + 7);
|
||||
updateCalendar();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 회원 정보를 가져오는 함수 (예시)
|
||||
function getMbrInnb() {
|
||||
// 실제 구현에서는 세션 스토리지나 다른 방법으로 회원 정보를 가져와야 합니다.
|
||||
return localStorage.getItem('mbrInnb') || '';
|
||||
}
|
||||
|
||||
function getMbrDvCd() {
|
||||
// 실제 구현에서는 세션 스토리지나 다른 방법으로 회원 구분 코드를 가져와야 합니다.
|
||||
return localStorage.getItem('mbrDvCd') || '';
|
||||
}
|
||||
|
||||
function loadIntakeChallengeDashboard() {
|
||||
$.ajax({
|
||||
url: baseUrl + '/getIntakechallengeDashboard',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
mbrInnb: getMbrInnb(),
|
||||
mbrDvCd: getMbrDvCd()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
updateDashboardUI(result);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('대시보드 로드 실패:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateDashboardUI(dashboardData) {
|
||||
// 연속 성공일 업데이트
|
||||
$('.inTit b').text(dashboardData.consecutiveSuccessDays);
|
||||
|
||||
// 누적 보상 정보 업데이트
|
||||
$('.reward01').text(formatNumber(dashboardData.accumulatedRewards.dailyReward) + '원');
|
||||
$('.reward02').text(formatNumber(dashboardData.accumulatedRewards.consecutiveBonus) + '원');
|
||||
$('.reward03').text(formatNumber(dashboardData.accumulatedRewards.couponCount) + '개');
|
||||
|
||||
// 월간 챌린지 현황 업데이트
|
||||
updateMonthlyChallengeSummary(dashboardData.monthlyChallengeSummary);
|
||||
}
|
||||
|
||||
function updateMonthlyChallengeSummary(summary) {
|
||||
const statsContainer = $('#stats-dates');
|
||||
statsContainer.empty();
|
||||
|
||||
summary.forEach(day => {
|
||||
const dayElement = $('<div>').addClass('day ' + day.status);
|
||||
dayElement.text(new Date(day.challengeDate).getDate());
|
||||
statsContainer.append(dayElement);
|
||||
});
|
||||
}
|
||||
|
||||
function formatNumber(num) {
|
||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
function updateMonthlySummary(monthlySummary) {
|
||||
const statsContainer = $('#stats-dates');
|
||||
statsContainer.empty();
|
||||
|
||||
monthlySummary.forEach(day => {
|
||||
const dayElement = $('<div>').addClass('day ' + day.status);
|
||||
dayElement.text(new Date(day.challengeDate).getDate());
|
||||
statsContainer.append(dayElement);
|
||||
});
|
||||
}
|
||||
// 섭취통계 시작
|
||||
const statsMonthNames = ["1월", "2월", "3월", "4월", "5월", "6월",
|
||||
"7월", "8월", "9월", "10월", "11월", "12월"];
|
||||
|
||||
let statsCurrentDate = new Date();
|
||||
const calendarContainer = document.getElementById('stats-dates');
|
||||
let isLoading = false;
|
||||
|
||||
//진행중인 상황 객체
|
||||
let statsDateClasses = {};
|
||||
|
||||
// statsDateClasses 부분을 초기화하는 함수 추가
|
||||
function loadStatsDateClasses() {
|
||||
$.ajax({
|
||||
url: baseUrl + '/getStatsDateClasses',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
mbrInnb: getMbrInnb(),
|
||||
mbrDvCd: getMbrDvCd()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
console.log("Loaded stats date classes:", result.data); // 로드된 데이터 확인
|
||||
statsDateClasses = result.data;
|
||||
renderStatsCalendar(statsCurrentDate);
|
||||
} else {
|
||||
console.error('Failed to load stats date classes:', result.message);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('AJAX request failed:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderStatsCalendar(date, position = 'bottom') {
|
||||
const statsDatesElement = document.getElementById('stats-dates');
|
||||
|
||||
const statsCurrentYear = date.getFullYear();
|
||||
const statsCurrentMonth = date.getMonth();
|
||||
|
||||
const monthYearText = `${statsMonthNames[statsCurrentMonth]} ${statsCurrentYear}`;
|
||||
|
||||
console.log(1);
|
||||
if (!statsDatesElement.innerHTML.includes(monthYearText)) {
|
||||
const statsFirstDay = new Date(statsCurrentYear, statsCurrentMonth, 1).getDay();
|
||||
const statsLastDate = new Date(statsCurrentYear, statsCurrentMonth + 1, 0).getDate();
|
||||
|
||||
const today = new Date();
|
||||
const isCurrentMonth = today.getFullYear() === statsCurrentYear && today.getMonth() === statsCurrentMonth;
|
||||
const todayDate = today.getDate();
|
||||
|
||||
const monthContainer = document.createElement('div');
|
||||
monthContainer.classList.add('month-container');
|
||||
|
||||
const monthHeader = document.createElement('div');
|
||||
monthHeader.classList.add('month-header');
|
||||
monthHeader.textContent = monthYearText;
|
||||
monthContainer.appendChild(monthHeader);
|
||||
|
||||
const daysRow = document.createElement('div');
|
||||
daysRow.classList.add('stats-days');
|
||||
const days = ["일", "월", "화", "수", "목", "금", "토"];
|
||||
days.forEach(day => {
|
||||
const dayElement = document.createElement('div');
|
||||
dayElement.textContent = day;
|
||||
daysRow.appendChild(dayElement);
|
||||
});
|
||||
monthContainer.appendChild(daysRow);
|
||||
|
||||
const datesGrid = document.createElement('div');
|
||||
datesGrid.classList.add('dates-grid');
|
||||
console.log(2);
|
||||
|
||||
for (let i = 0; i < statsFirstDay; i++) {
|
||||
const statsEmptyCell = document.createElement('div');
|
||||
datesGrid.appendChild(statsEmptyCell);
|
||||
}
|
||||
console.log(3);
|
||||
|
||||
for (let statsDate = 1; statsDate <= statsLastDate; statsDate++) {
|
||||
const statsDateElement = document.createElement('div');
|
||||
const dateSpan = document.createElement('span');
|
||||
dateSpan.textContent = statsDate;
|
||||
statsDateElement.appendChild(dateSpan);
|
||||
|
||||
const fullDate = `${statsCurrentYear}-${String(statsCurrentMonth + 1).padStart(2, '0')}-${String(statsDate).padStart(2, '0')}`;
|
||||
|
||||
// 콘솔 로그 추가
|
||||
console.log(`Checking date: ${fullDate}`);
|
||||
if (statsDateClasses[fullDate]) {
|
||||
console.log(`Applying class '${statsDateClasses[fullDate]}' to date ${fullDate}`); // 클래스 적용 확인
|
||||
statsDateElement.classList.add(statsDateClasses[fullDate]);
|
||||
}
|
||||
|
||||
if (isCurrentMonth && statsDate === todayDate) {
|
||||
statsDateElement.classList.add('today');
|
||||
}
|
||||
datesGrid.appendChild(statsDateElement);
|
||||
}
|
||||
|
||||
monthContainer.appendChild(datesGrid);
|
||||
console.log(4);
|
||||
|
||||
if (position === 'top') {
|
||||
statsDatesElement.prepend(monthContainer);
|
||||
} else {
|
||||
statsDatesElement.appendChild(monthContainer);
|
||||
}
|
||||
console.log(5);
|
||||
|
||||
hideAfterStatsDone(datesGrid);
|
||||
}
|
||||
}
|
||||
|
||||
function loadPreviousMonth() {
|
||||
const newDate = new Date(statsCurrentDate.getFullYear(), statsCurrentDate.getMonth() - 1, 1);
|
||||
renderStatsCalendar(newDate, 'top');
|
||||
statsCurrentDate = newDate;
|
||||
}
|
||||
|
||||
function loadNextMonth() {
|
||||
const newDate = new Date(statsCurrentDate.getFullYear(), statsCurrentDate.getMonth() + 1, 1);
|
||||
renderStatsCalendar(newDate, 'bottom');
|
||||
statsCurrentDate = newDate;
|
||||
}
|
||||
|
||||
function hideAfterStatsDone(datesGrid) {
|
||||
const statsDoneElements = datesGrid.querySelectorAll('.stats_done');
|
||||
statsDoneElements.forEach((element) => {
|
||||
const nextElement = element.nextElementSibling;
|
||||
if (nextElement && !nextElement.classList.contains('stats_done') && !nextElement.classList.contains('stats_30done')) {
|
||||
element.classList.add('hide-after');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//섭취완료 스크립트
|
||||
document.addEventListener('click', function(event) {
|
||||
if (event.target.classList.contains('drug_off')) {
|
||||
event.preventDefault();
|
||||
|
||||
event.target.classList.remove('drug_off');
|
||||
event.target.classList.add('drug_on');
|
||||
event.target.textContent = '섭취완료';
|
||||
|
||||
// 섭취 완료 후 클릭 이벤트 제거
|
||||
event.target.style.pointerEvents = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
function loadCurrentChallengeProducts() {
|
||||
$.ajax({
|
||||
url: baseUrl + '/selectCurrentChallengeProducts',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
mbrInnb: getMbrInnb(),
|
||||
mbrDvCd: getMbrDvCd()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.success) {
|
||||
updateCurrentChallengeProductsUI(result.currentChallengeProducts);
|
||||
} else {
|
||||
alert('현재 챌린지 중인 제품을 불러오는데 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('AJAX 요청 실패:', error);
|
||||
alert('서버 오류가 발생했습니다. 다시 시도해 주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateCurrentChallengeProductsUI(products) {
|
||||
const container = $('#challengeProductWrap');
|
||||
container.empty();
|
||||
|
||||
products.forEach(function(product) {
|
||||
const productHtml = `
|
||||
<div class="challengeProduct">
|
||||
<a href="#">
|
||||
<div class="thum"><img src="../resources/images/event/discount_thum3.png" alt="썸네일"></div>
|
||||
<div class="cpTit">
|
||||
<p class="tit">${product.goodsNm}</p>
|
||||
<p class="dayCheck">1일 ${product.ntkCnt}회</p>
|
||||
</div>
|
||||
<div class="drugCheck">
|
||||
${createIntakeButtons(product.dailyIntakeCount, product.ntkCnt)}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
container.append(productHtml);
|
||||
});
|
||||
}
|
||||
|
||||
function openDeleteModal() {
|
||||
MicroModal.show('modal-1', {
|
||||
onClose: function() {
|
||||
// 모달이 닫힐 때 이벤트 리스너 제거
|
||||
$('#modal-1 .microModal__btn-primary').off('click');
|
||||
}
|
||||
});
|
||||
|
||||
// 모달의 "예" 버튼에 클릭 이벤트 리스너 추가
|
||||
$('#modal-1 .microModal__btn-primary').on('click', function() {
|
||||
deleteProduct();
|
||||
MicroModal.close('modal-1');
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
addToChallenge: addToChallenge,
|
||||
handleDateClick: handleDateClick, // 외부에서 호출할 수 있도록 함수를 노출
|
||||
navigateToAddProduct: navigateToAddProduct, // 외부에서 호출할 수 있도록 함수를 노출
|
||||
updateMonthlySummary: updateMonthlySummary,
|
||||
goToProductDetail: goToProductDetail,
|
||||
goToAddProduct: goToAddProduct,
|
||||
deleteProduct: deleteProduct,
|
||||
openDeleteModal: openDeleteModal
|
||||
};
|
||||
})();
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
Intakchl.init();
|
||||
calendarContainer.scrollTop = calendarContainer.scrollHeight / 2; // Start in the middle
|
||||
calendarContainer.addEventListener('scroll', handleScroll);
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
Intakchl.init({
|
||||
bnfInnb: $('input[name="bnfInnb"]').val(),
|
||||
dailyIntakeCount: parseInt($('#count').text(), 10)
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,302 @@
|
||||
var IntakchlAlarmSettings = (function() {
|
||||
"use strict";
|
||||
|
||||
const baseUrl = '/sopmal/bnft';
|
||||
let alarmStatuses = [];
|
||||
let isAgreed = false;
|
||||
let bnfInnb;
|
||||
let bnfNtkInnb;
|
||||
let currentAlarmIndex = -1;
|
||||
|
||||
function init(screenInfoData) {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
bnfInnb = urlParams.get('bnfInnb');
|
||||
bnfNtkInnb = urlParams.get('bnfNtkInnb');
|
||||
|
||||
if (screenInfoData && screenInfoData.alarmStatuses && screenInfoData.alarmStatuses.length > 0) {
|
||||
alarmStatuses = screenInfoData.alarmStatuses;
|
||||
|
||||
// 기본 알람 설정을 유지하기 위해 부족한 알람을 채워 넣습니다.
|
||||
while (alarmStatuses.length < 3) {
|
||||
const defaultAlarm = {
|
||||
bnfNtkNtcnInnb: alarmStatuses.length + 1,
|
||||
ntcnTme: alarmStatuses.length === 0 ? '07:00:00' : (alarmStatuses.length === 1 ? '12:00:00' : '19:00:00'),
|
||||
useAt: 'N'
|
||||
};
|
||||
alarmStatuses.push(defaultAlarm);
|
||||
}
|
||||
|
||||
} else {
|
||||
alarmStatuses = [
|
||||
{ bnfNtkNtcnInnb: 1, ntcnTme: '07:00:00', useAt: 'N' },
|
||||
{ bnfNtkNtcnInnb: 2, ntcnTme: '12:00:00', useAt: 'N' },
|
||||
{ bnfNtkNtcnInnb: 3, ntcnTme: '19:00:00', useAt: 'N' }
|
||||
];
|
||||
}
|
||||
|
||||
isAgreed = screenInfoData.isAgreed || false;
|
||||
initTimePicker();
|
||||
initAlarmSettings();
|
||||
bindEvents();
|
||||
updateAlarmSettingsVisibility();
|
||||
}
|
||||
|
||||
function initTimePicker() {
|
||||
const hourSelect = document.getElementById('hour-select');
|
||||
const minuteSelect = document.getElementById('minute-select');
|
||||
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
const option = document.createElement('option');
|
||||
option.value = i.toString().padStart(2, '0');
|
||||
option.textContent = i.toString().padStart(2, '0');
|
||||
hourSelect.appendChild(option);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 60; i += 10) {
|
||||
const option = document.createElement('option');
|
||||
option.value = i.toString().padStart(2, '0');
|
||||
option.textContent = i.toString().padStart(2, '0');
|
||||
minuteSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
|
||||
function initAlarmSettings() {
|
||||
const alarmList = document.querySelector('.alarmList');
|
||||
if (!alarmList) return;
|
||||
|
||||
alarmList.innerHTML = '';
|
||||
|
||||
alarmStatuses.forEach((status, index) => {
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = `
|
||||
<span><a data-micromodal-trigger="modal-1" id="alarmTime${index + 1}" data-bnfNtkNtcnInnb="${status.bnfNtkNtcnInnb}">${formatTime(status.ntcnTme)}</a></span>
|
||||
<fieldset class="toggle">
|
||||
<label>
|
||||
<input role="switch" type="checkbox" id="alarmToggle${index + 1}" ${status.useAt === 'Y' ? 'checked' : ''}>
|
||||
</label>
|
||||
</fieldset>
|
||||
`;
|
||||
alarmList.appendChild(li);
|
||||
});
|
||||
|
||||
document.getElementById('mainAlarmToggle').checked = isAgreed;
|
||||
|
||||
bindAlarmEvents();
|
||||
}
|
||||
|
||||
function bindAlarmEvents() {
|
||||
document.querySelectorAll('[id^="alarmToggle"]').forEach((toggle, index) => {
|
||||
toggle.addEventListener('change', (e) => {
|
||||
alarmStatuses[index].useAt = e.target.checked ? 'Y' : 'N';
|
||||
saveAlarmSettings(index);
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('[id^="alarmTime"]').forEach((timeElement, index) => {
|
||||
timeElement.addEventListener('click', () => {
|
||||
currentAlarmIndex = index;
|
||||
setupTimePicker(index);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
const mainAlarmToggle = document.getElementById('mainAlarmToggle');
|
||||
if (mainAlarmToggle) {
|
||||
mainAlarmToggle.addEventListener('change', (e) => {
|
||||
isAgreed = e.target.checked;
|
||||
saveAgreementStatus();
|
||||
updateAlarmSettingsVisibility();
|
||||
});
|
||||
}
|
||||
|
||||
const agreeCheckbox = document.querySelector('input[role="switch"]');
|
||||
if (agreeCheckbox) {
|
||||
agreeCheckbox.addEventListener('change', (e) => {
|
||||
isAgreed = e.target.checked;
|
||||
saveAgreementStatus();
|
||||
updateAlarmSettingsVisibility();
|
||||
});
|
||||
}
|
||||
|
||||
MicroModal.init({
|
||||
onShow: (modal) => {
|
||||
setupTimePicker(currentAlarmIndex);
|
||||
},
|
||||
onClose: (modal) => {
|
||||
saveTimePickerSelection();
|
||||
}
|
||||
});
|
||||
|
||||
const modal = document.getElementById('modal-1');
|
||||
if (modal) {
|
||||
const ampmElem = modal.querySelector('#ampm');
|
||||
const hourElem = modal.querySelector('#hour');
|
||||
const minuteElem = modal.querySelector('#minute');
|
||||
|
||||
if (ampmElem) ampmElem.addEventListener('click', () => showSelect('ampm'));
|
||||
if (hourElem) hourElem.addEventListener('click', () => showSelect('hour'));
|
||||
if (minuteElem) minuteElem.addEventListener('click', () => showSelect('minute'));
|
||||
|
||||
modal.querySelectorAll('.challenge-arrow').forEach(arrow => {
|
||||
arrow.addEventListener('click', function() {
|
||||
const type = this.parentElement.querySelector('.challenge-value').id;
|
||||
adjustValue(type, -1);
|
||||
});
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.challenge-next').forEach(next => {
|
||||
next.addEventListener('click', function() {
|
||||
const type = this.parentElement.querySelector('.challenge-value').id;
|
||||
adjustValue(type, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateAlarmSettingsVisibility() {
|
||||
const alarmToggles = document.querySelectorAll('[id^="alarmToggle"]');
|
||||
const alarmTimes = document.querySelectorAll('[id^="alarmTime"]');
|
||||
|
||||
alarmToggles.forEach(toggle => {
|
||||
toggle.disabled = !isAgreed;
|
||||
});
|
||||
|
||||
alarmTimes.forEach(time => {
|
||||
time.style.pointerEvents = isAgreed ? 'auto' : 'none';
|
||||
time.style.opacity = isAgreed ? '1' : '0.5';
|
||||
});
|
||||
}
|
||||
|
||||
function saveAgreementStatus() {
|
||||
var agreementStatus = isAgreed ? 'Y' : 'N';
|
||||
|
||||
$.ajax({
|
||||
url: baseUrl + '/updateAlarmAgreement',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
agreAt: agreementStatus
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
console.log('Alarm agreement status updated successfully');
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Failed to update alarm agreement status:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function saveAlarmSettings(index) {
|
||||
const status = alarmStatuses[index];
|
||||
const bnfNtkNtcnInnb = document.getElementById(`alarmTime${index + 1}`).getAttribute('data-bnfNtkNtcnInnb');
|
||||
|
||||
$.ajax({
|
||||
url: baseUrl + '/saveAlarmSettings',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: bnfInnb,
|
||||
bnfNtkInnb: bnfNtkInnb,
|
||||
bnfNtkNtcnInnb: bnfNtkNtcnInnb, // 이 값을 전송합니다
|
||||
ntcnTme: status.ntcnTme,
|
||||
useAt: status.useAt
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
console.log('Alarm setting saved successfully');
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Failed to save alarm setting:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setupTimePicker(index) {
|
||||
const currentSetting = alarmStatuses[index];
|
||||
const [hours, minutes] = currentSetting.ntcnTme.split(':');
|
||||
const date = new Date();
|
||||
date.setHours(parseInt(hours, 10));
|
||||
date.setMinutes(parseInt(minutes, 10));
|
||||
|
||||
document.getElementById('ampm').textContent = date.getHours() >= 12 ? '오후' : '오전';
|
||||
document.getElementById('hour').textContent = (date.getHours() % 12 || 12).toString().padStart(2, '0');
|
||||
document.getElementById('minute').textContent = date.getMinutes().toString().padStart(2, '0');
|
||||
}
|
||||
|
||||
function saveTimePickerSelection() {
|
||||
if (currentAlarmIndex === -1) return;
|
||||
|
||||
const ampm = document.getElementById('ampm').textContent;
|
||||
let hour = parseInt(document.getElementById('hour').textContent, 10);
|
||||
const minute = document.getElementById('minute').textContent;
|
||||
|
||||
if (ampm === '오후' && hour !== 12) hour += 12;
|
||||
if (ampm === '오전' && hour === 12) hour = 0;
|
||||
|
||||
const newTime = `${hour.toString().padStart(2, '0')}:${minute}:00`;
|
||||
if (alarmStatuses[currentAlarmIndex].ntcnTme !== newTime) {
|
||||
alarmStatuses[currentAlarmIndex].ntcnTme = newTime;
|
||||
document.getElementById(`alarmTime${currentAlarmIndex + 1}`).textContent = formatTime(newTime);
|
||||
saveAlarmSettings(currentAlarmIndex);
|
||||
}
|
||||
}
|
||||
|
||||
function formatTime(timeString) {
|
||||
const [hours, minutes] = timeString.split(':');
|
||||
const date = new Date();
|
||||
date.setHours(parseInt(hours, 10));
|
||||
date.setMinutes(parseInt(minutes, 10));
|
||||
const ampm = date.getHours() >= 12 ? '오후' : '오전';
|
||||
const formattedHours = date.getHours() % 12 || 12;
|
||||
return `${ampm} ${formattedHours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function adjustValue(type, direction) {
|
||||
const elem = document.getElementById(type);
|
||||
const select = document.getElementById(`${type}-select`);
|
||||
let currentValue = parseInt(elem.textContent, 10);
|
||||
|
||||
if (type === 'hour') {
|
||||
currentValue = (currentValue + direction + 12 - 1) % 12 + 1;
|
||||
elem.textContent = currentValue.toString().padStart(2, '0');
|
||||
} else if (type === 'minute') {
|
||||
let currentIndex = Array.from(select.options).findIndex(option => option.value === elem.textContent);
|
||||
currentIndex = (currentIndex + direction + select.options.length) % select.options.length;
|
||||
elem.textContent = select.options[currentIndex].value;
|
||||
} else if (type === 'ampm') {
|
||||
elem.textContent = elem.textContent === '오전' ? '오후' : '오전';
|
||||
}
|
||||
}
|
||||
|
||||
function showSelect(type) {
|
||||
const elem = document.getElementById(type);
|
||||
const select = document.getElementById(`${type}-select`);
|
||||
elem.style.display = 'none';
|
||||
select.style.display = 'inline-block';
|
||||
select.value = elem.textContent;
|
||||
select.focus();
|
||||
}
|
||||
|
||||
function updateValue(type) {
|
||||
const elem = document.getElementById(type);
|
||||
const select = document.getElementById(`${type}-select`);
|
||||
elem.textContent = select.value;
|
||||
elem.style.display = 'inline-block';
|
||||
select.style.display = 'none';
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
adjustValue: adjustValue,
|
||||
showSelect: showSelect,
|
||||
updateValue: updateValue
|
||||
};
|
||||
})();
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const isAgreed = document.querySelector('input[role="switch"]').checked;
|
||||
// screenInfoData 객체가 이미 설정된 경우 이 값을 사용하고, 그렇지 않으면 기본 값을 사용합니다.
|
||||
const alarmStatuses = window.alarmStatuses || screenInfoData.alarmStatuses;
|
||||
IntakchlAlarmSettings.init({ alarmStatuses: alarmStatuses, isAgreed: isAgreed });
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
document.getElementById('manageProducts').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = '/sopmal/bnft/intakchlChallengeProductManagement';
|
||||
});
|
||||
|
||||
document.getElementById('setAlarms').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = '/sopmal/bnft/intakchllAlarmSettings';
|
||||
});
|
||||
@@ -0,0 +1,219 @@
|
||||
$(document).ready(function() {
|
||||
let canvas = $('.scrachMask')[0];
|
||||
let ctx = canvas.getContext('2d');
|
||||
let isDrawing = false;
|
||||
let totalPixels;
|
||||
let clearedPixels = 0;
|
||||
let isPopupShown = false;
|
||||
let prize;
|
||||
let bnfInnb = screenInfo.bnfInnb;
|
||||
|
||||
function resizeCanvas() {
|
||||
canvas.width = $('.luckyScrachBox').width();
|
||||
canvas.height = $('.luckyScrachBox').height();
|
||||
|
||||
// Create a linear gradient
|
||||
let gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
|
||||
gradient.addColorStop(0, '#d3d3d3');
|
||||
gradient.addColorStop(0.25, '#e9e9e9');
|
||||
gradient.addColorStop(0.5, '#ddd');
|
||||
gradient.addColorStop(0.75, '#eee');
|
||||
gradient.addColorStop(1, '#ddd');
|
||||
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
totalPixels = canvas.width * canvas.height;
|
||||
}
|
||||
|
||||
function loadImage(imageType, imagePath, $img) {
|
||||
if (!imagePath) {
|
||||
console.warn(`Image path for ${imageType} is not available`);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($img.length) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/image',
|
||||
method: 'GET',
|
||||
data: { path: imagePath },
|
||||
xhrFields: { responseType: 'blob' },
|
||||
success: function(data) {
|
||||
const imageUrl = URL.createObjectURL(data);
|
||||
$img.attr('src', imageUrl);
|
||||
console.log(`${imageType} image loaded successfully`);
|
||||
},
|
||||
error: function() {
|
||||
console.error(`Failed to load ${imageType} image`);
|
||||
$img.attr('src', '/path/to/fallback-image.jpg');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(`Image element not found for ${imageType}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Load images
|
||||
function loadImages() {
|
||||
console.log('Starting to load images');
|
||||
loadImage('representative', screenInfo.representativeImagePath, $('.LottoImg img'));
|
||||
}
|
||||
|
||||
function getOffset(e) {
|
||||
let offset = $(canvas).offset();
|
||||
let x = (e.pageX || e.originalEvent.touches[0].pageX) - offset.left;
|
||||
let y = (e.pageY || e.originalEvent.touches[0].pageY) - offset.top;
|
||||
return { x: x, y: y };
|
||||
}
|
||||
|
||||
function checkClearedPercentage() {
|
||||
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
let pixels = imageData.data;
|
||||
clearedPixels = 0;
|
||||
|
||||
for (let i = 3; i < pixels.length; i += 4) {
|
||||
if (pixels[i] === 0) {
|
||||
clearedPixels++;
|
||||
}
|
||||
}
|
||||
|
||||
let clearedPercentage = (clearedPixels / totalPixels) * 100;
|
||||
if (clearedPercentage > 90 && !isPopupShown) {
|
||||
isPopupShown = true;
|
||||
showPrize(prize);
|
||||
}
|
||||
}
|
||||
|
||||
function determinePrize() {
|
||||
return new Promise((resolve, reject) => {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/participateLuckyLottery', // 백엔드 엔드포인트
|
||||
type: 'POST',
|
||||
data: JSON.stringify({
|
||||
mbrInnb: 87626,
|
||||
mbrDvCd: 'GC',
|
||||
bnfInnb: bnfInnb
|
||||
}), // 필요한 데이터 포함
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
// JSON 문자열을 파싱하여 객체로 변환
|
||||
let result = JSON.parse(response.resBody.result);
|
||||
console.log(result);
|
||||
// rank 값을 추출
|
||||
let rank = result.rank;
|
||||
console.log(rank);
|
||||
resolve(rank); // rank 값을 반환
|
||||
},
|
||||
error: function(error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showPrize(prize) {
|
||||
switch (prize) {
|
||||
case 1:
|
||||
// 1등 당첨 팝업 내용
|
||||
$('#modal-1 .microModal__title').html('축하합니다!<br>1등 당첨!');
|
||||
$('#modal-1 .modal-icon-present').html('선물');
|
||||
$('#modal-1 .sub_tit').html('초임계 식물성 알티지 오메가3');
|
||||
$('#modal-1 p:last-child').html('MY혜택 > 쿠폰에서 확인하세요.');
|
||||
MicroModal.show('modal-1');
|
||||
break;
|
||||
case 2:
|
||||
// 2등 당첨 팝업 내용
|
||||
$('#modal-1 .microModal__title').html('축하합니다!<br>2등 당첨!');
|
||||
$('#modal-1 .modal-icon-present').html('포인트');
|
||||
$('#modal-1 .sub_tit').html('마일리지 5000점 적립');
|
||||
$('#modal-1 p:last-child').html('MY혜택 > 포인트에서 확인하세요.');
|
||||
MicroModal.show('modal-1');
|
||||
break;
|
||||
case 3:
|
||||
// 3등 당첨 팝업 내용
|
||||
$('#modal-1 .microModal__title').html('축하합니다!<br>3등 당첨!');
|
||||
$('#modal-1 .modal-icon-present').html('포인트');
|
||||
$('#modal-1 .sub_tit').html('10% 할인 쿠폰');
|
||||
$('#modal-1 p:last-child').html('MY혜택 > 쿠폰에서 확인하세요.');
|
||||
MicroModal.show('modal-1');
|
||||
break;
|
||||
default:
|
||||
// 미당첨 팝업 내용
|
||||
MicroModal.show('modal-2');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$(window).resize(resizeCanvas);
|
||||
resizeCanvas();
|
||||
loadImages();
|
||||
|
||||
$(canvas).on('mousedown touchstart', function(e) {
|
||||
if (isDrawing || clearedPixels / totalPixels * 100 > 90) return; // 스크래치가 진행 중이거나 다 긁힌 경우 이벤트 무시
|
||||
isDrawing = true;
|
||||
// 스크래치를 시작할 때 당첨을 결정
|
||||
determinePrize().then(result => {
|
||||
prize = result;
|
||||
switch (prize) {
|
||||
case 1:
|
||||
$('.scrachGift').html(`
|
||||
<li><img src="/mobile/images/bnft/lucky_award1.svg" alt="1등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award1.svg" alt="1등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award1.svg" alt="1등"></li>
|
||||
`);
|
||||
break;
|
||||
case 2:
|
||||
$('.scrachGift').html(`
|
||||
<li><img src="/mobile/images/bnft/lucky_award2.svg" alt="2등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award2.svg" alt="2등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award2.svg" alt="2등"></li>
|
||||
`);
|
||||
break;
|
||||
case 3:
|
||||
$('.scrachGift').html(`
|
||||
<li><img src="/mobile/images/bnft/lucky_award3.svg" alt="3등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award3.svg" alt="3등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award3.svg" alt="3등"></li>
|
||||
`);
|
||||
break;
|
||||
default:
|
||||
// 실패 시 이미지 배치
|
||||
$('.scrachGift').html(`
|
||||
<li><img src="/mobile/images/bnft/lucky_award1.svg" alt="1등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award1.svg" alt="1등"></li>
|
||||
<li><img src="/mobile/images/bnft/lucky_award3.svg" alt="3등"></li>
|
||||
`);
|
||||
break;
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error determining prize:', error);
|
||||
isDrawing = false; // 에러 발생 시 플래그 리셋
|
||||
});
|
||||
});
|
||||
|
||||
$(canvas).on('mousemove touchmove', function(e) {
|
||||
if (!isDrawing) return;
|
||||
e.preventDefault();
|
||||
let pos = getOffset(e);
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.beginPath();
|
||||
ctx.arc(pos.x, pos.y, 20, 0, Math.PI * 2, false);
|
||||
ctx.fill();
|
||||
checkClearedPercentage(); // Check cleared percentage after each draw
|
||||
if (clearedPixels / totalPixels * 100 > 90) {
|
||||
isDrawing = false; // 스크래치 완료 후 플래그 리셋
|
||||
}
|
||||
});
|
||||
|
||||
$(canvas).on('mouseup touchend', function() {
|
||||
isDrawing = false;
|
||||
});
|
||||
|
||||
$('.microModal__btnContainer').click(function() {
|
||||
MicroModal.close();
|
||||
isPopupShown = false;
|
||||
resizeCanvas(); // Reset the canvas
|
||||
isDrawing = false; // 스크래치 완료 후 플래그 리셋
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,162 @@
|
||||
const Lvshop = (function() {
|
||||
let timer;
|
||||
let remainingTime;
|
||||
let currentLvshopId;
|
||||
let startTime;
|
||||
let currentMlgRwdAmt;
|
||||
let lvshopWindow;
|
||||
let checkWindowInterval;
|
||||
let isWindowClosedByUser = false;
|
||||
|
||||
function start(bnfInnb, linkUrl, seconds, mlgRwdAmt) {
|
||||
if (isLvshopAccumulated(bnfInnb)) {
|
||||
alert('이미 적립이 완료된 라이브쇼핑입니다.');
|
||||
window.open(linkUrl, 'lvshopView', 'width=800,height=600');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/startLvshop',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: bnfInnb }),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
currentLvshopId = bnfInnb;
|
||||
remainingTime = seconds;
|
||||
startTime = new Date().getTime();
|
||||
currentMlgRwdAmt = mlgRwdAmt;
|
||||
isWindowClosedByUser = false;
|
||||
|
||||
openLvshopWindow(linkUrl);
|
||||
startTimer();
|
||||
startWindowCheck();
|
||||
} else {
|
||||
alert(response.message || '라이브쇼핑 시작에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('라이브쇼핑 시작 요청 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openLvshopWindow(url) {
|
||||
lvshopWindow = window.open(url, 'lvshopView', 'width=800,height=600');
|
||||
if (!lvshopWindow) {
|
||||
alert('팝업 차단을 해제해주세요.');
|
||||
}
|
||||
}
|
||||
|
||||
function startWindowCheck() {
|
||||
clearInterval(checkWindowInterval);
|
||||
checkWindowInterval = setInterval(function() {
|
||||
if (!lvshopWindow || lvshopWindow.closed) {
|
||||
clearInterval(checkWindowInterval);
|
||||
clearInterval(timer);
|
||||
isWindowClosedByUser = true;
|
||||
handleLvshopEnd();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
clearInterval(timer);
|
||||
timer = setInterval(function() {
|
||||
remainingTime--;
|
||||
|
||||
if (remainingTime <= 0) {
|
||||
clearInterval(timer);
|
||||
handleLvshopEnd();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function handleLvshopEnd() {
|
||||
if (isWindowClosedByUser) {
|
||||
alert('마일리지 적립이 안되었습니다. 라이브쇼핑 시청을 완료해야 마일리지가 적립됩니다.');
|
||||
} else {
|
||||
completeMileageAccumulation();
|
||||
}
|
||||
}
|
||||
|
||||
function completeMileageAccumulation() {
|
||||
let endTime = new Date().getTime();
|
||||
let duration = (endTime - startTime) / 1000;
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/completeLvshopMileageAccumulation',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: currentLvshopId,
|
||||
duration: duration,
|
||||
mlgRwdAmt: currentMlgRwdAmt
|
||||
}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
alert('마일리지가 적립되었습니다!');
|
||||
updateLvshopStatus(currentLvshopId);
|
||||
if (lvshopWindow && !lvshopWindow.closed) {
|
||||
lvshopWindow.close();
|
||||
}
|
||||
} else {
|
||||
alert(response.message || '마일리지 적립에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error:', error);
|
||||
alert('마일리지 적립 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isLvshopAccumulated(bnfInnb) {
|
||||
return $(`.li_mile[data-bnf-innb="${bnfInnb}"]`).hasClass('on');
|
||||
}
|
||||
|
||||
function updateLvshopStatus(bnfInnb) {
|
||||
const mileElement = $(`.li_mile[data-bnf-innb="${bnfInnb}"]`);
|
||||
mileElement.addClass('on').find('span').text('적립완료');
|
||||
}
|
||||
|
||||
function toggleNotification() {
|
||||
const button = $('.liveShopping__btnControls .live_btn');
|
||||
|
||||
// 이미 알림 신청이 완료된 상태라면 함수 실행 중지
|
||||
if (!button.hasClass('outline')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/toggleLvshopNotification',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
const button = $('.live_btn.outline');
|
||||
if (response.isSubscribed) {
|
||||
button.removeClass('outline');
|
||||
button.html('<i class="ico_alarm2"></i>라이브쇼핑 알림신청 완료');
|
||||
} else {
|
||||
button.addClass('outline');
|
||||
button.html('<i class="ico_alarm2"></i>라이브쇼핑 알림신청');
|
||||
}
|
||||
} else {
|
||||
alert(response.message || '알림 설정 변경에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert('알림 설정 변경 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
start: start,
|
||||
toggleNotification: toggleNotification
|
||||
};
|
||||
})();
|
||||
|
||||
console.log('Lvshop script loaded');
|
||||
@@ -0,0 +1,218 @@
|
||||
const OXQuiz = (function() {
|
||||
function init() {
|
||||
loadImages();
|
||||
addEventListeners();
|
||||
getNotificationStatus();
|
||||
}
|
||||
|
||||
function loadImages() {
|
||||
if (screenInfo.basicInfo) {
|
||||
const imagePath = screenInfo.basicInfo.scrReprsntImg;
|
||||
loadImage('quizThumnail', imagePath, $('.quizThumnail img'));
|
||||
}
|
||||
}
|
||||
|
||||
function loadImage(imageType, imagePath, $img) {
|
||||
if ($img.length) {
|
||||
$img.attr('src', imagePath);
|
||||
console.log(`${imageType} image loaded successfully`);
|
||||
} else {
|
||||
console.warn(`Image element not found for ${imageType}`);
|
||||
}
|
||||
}
|
||||
|
||||
function addEventListeners() {
|
||||
$('#quizResult').on('click', handleQuizResult);
|
||||
$('.qzSelect a').on('click', handleAnswerSelection);
|
||||
$('#notificationBtn').on('click', handleNotification);
|
||||
}
|
||||
|
||||
function handleAnswerSelection(e) {
|
||||
e.preventDefault();
|
||||
$('.qzSelect a').removeClass('on');
|
||||
$(this).addClass('on');
|
||||
}
|
||||
|
||||
function handleQuizResult() {
|
||||
const selectedAnswer = $('.qzSelect a.on').data('answer');
|
||||
if (!selectedAnswer) {
|
||||
alert('OX 중 한 가지를 선택해 주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/participate',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: screenInfo.basicInfo.bnfInnb,
|
||||
bnfQuizInnb: screenInfo.quizInfoList[screenInfo.currentQuiz - 1].bnfQuizInnb,
|
||||
answCn: selectedAnswer
|
||||
}),
|
||||
success: handleQuizResponse,
|
||||
error: handleQuizError
|
||||
});
|
||||
}
|
||||
|
||||
function handleQuizResponse(response) {
|
||||
if (response.success) {
|
||||
updateQuizState(response);
|
||||
showResultModal(response);
|
||||
} else {
|
||||
alert(response.message || '퀴즈 참여에 실패했습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
function handleQuizError(xhr, status, error) {
|
||||
console.error('퀴즈 참여 실패:', error);
|
||||
let errorMessage = '퀴즈 참여 중 오류가 발생했습니다. ';
|
||||
if (xhr.status === 404) {
|
||||
errorMessage += '퀴즈를 찾을 수 없습니다. 페이지를 새로고침 해주세요.';
|
||||
} else if (xhr.status === 403) {
|
||||
errorMessage += '권한이 없습니다. 로그인 상태를 확인해주세요.';
|
||||
} else {
|
||||
errorMessage += '잠시 후 다시 시도해주세요.';
|
||||
}
|
||||
alert(errorMessage);
|
||||
}
|
||||
|
||||
function showResultModal(response) {
|
||||
let modalId;
|
||||
if (response.rewardCode === '13030') {
|
||||
modalId = 'modal-3'; // 모든 퀴즈 정답
|
||||
} else if (response.isCorrect) {
|
||||
modalId = 'modal-1'; // 정답
|
||||
} else {
|
||||
modalId = 'modal-2'; // 오답
|
||||
}
|
||||
|
||||
MicroModal.show(modalId, {
|
||||
onClose: function() {
|
||||
moveToNextQuiz();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleNotification() {
|
||||
const currentStatus = $(this).data('status');
|
||||
const newStatus = currentStatus === 'on' ? 'off' : 'on';
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/updateoxquizNotificationStatus',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: screenInfo.basicInfo.bnfInnb,
|
||||
agreAt: newStatus === 'on' ? 'Y' : 'N'
|
||||
}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
updateNotificationButton(newStatus === 'on');
|
||||
} else {
|
||||
alert('알림 상태 변경에 실패했습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('알림 상태 변경 실패:', error);
|
||||
alert('알림 상태 변경 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getNotificationStatus() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/getoxquizNotificationStatus',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ bnfInnb: screenInfo.basicInfo.bnfInnb }),
|
||||
success: function(response) {
|
||||
updateNotificationButton(response.notificationStatus);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('알림 상태 조회 실패:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateNotificationButton(isNotificationOn) {
|
||||
const $notificationBtn = $('.live_btn.outline');
|
||||
const $notificationText = $notificationBtn.find('span');
|
||||
const $notificationIcon = $notificationBtn.find('i');
|
||||
if (isNotificationOn) {
|
||||
$notificationText.text('알림 신청 완료');
|
||||
$notificationBtn.data('status', 'on').removeClass('outline');
|
||||
$notificationIcon.removeClass('ico_alarm2').addClass('ico_alarm_on');
|
||||
} else {
|
||||
$notificationText.text('알림 신청');
|
||||
$notificationBtn.data('status', 'off').addClass('outline');
|
||||
$notificationIcon.removeClass('ico_alarm_on').addClass('ico_alarm2');
|
||||
}
|
||||
}
|
||||
|
||||
function updateQuizState(quizResult) {
|
||||
screenInfo.quizInfoList[screenInfo.currentQuiz - 1].userAnswer = quizResult.userAnswer;
|
||||
screenInfo.quizInfoList[screenInfo.currentQuiz - 1].isCorrect = quizResult.isCorrect ? 'O' : 'X';
|
||||
updateQuizUI();
|
||||
}
|
||||
|
||||
function updateQuizUI() {
|
||||
// 퀴즈 스탬프 업데이트
|
||||
$('.quizStamp li').each(function(index) {
|
||||
const quizInfo = screenInfo.quizInfoList[index];
|
||||
$(this).removeClass('on fail location');
|
||||
if (quizInfo.isCorrect === 'O') {
|
||||
$(this).addClass('on');
|
||||
} else if (quizInfo.isCorrect === 'X') {
|
||||
$(this).addClass('on fail');
|
||||
}
|
||||
if (index + 1 === screenInfo.currentQuiz) {
|
||||
$(this).addClass('location');
|
||||
}
|
||||
});
|
||||
|
||||
// 현재 퀴즈 내용 업데이트
|
||||
const currentQuiz = screenInfo.quizInfoList[screenInfo.currentQuiz - 1];
|
||||
$('.quizBox .txt').text(currentQuiz.quizCn);
|
||||
$('.bottomBtnControls button:last-child').prop('disabled', currentQuiz.userAnswer !== null);
|
||||
|
||||
// 힌트 URL 업데이트
|
||||
$('.bottomBtnControls button:first-child').attr('onclick', `window.open('${currentQuiz.hintUrl}', '_blank')`);
|
||||
|
||||
const $resultButton = $('.bottomBtnControls button:last-child');
|
||||
if (currentQuiz.userAnswer !== null) {
|
||||
$resultButton.text('도전완료').prop('disabled', true).removeClass('theme').addClass('gray');
|
||||
} else {
|
||||
$resultButton.text('결과확인').prop('disabled', false).removeClass('gray').addClass('theme');
|
||||
}
|
||||
}
|
||||
|
||||
function moveToNextQuiz() {
|
||||
if (screenInfo.currentQuiz < screenInfo.quizCount) {
|
||||
screenInfo.currentQuiz++;
|
||||
updateQuizUI();
|
||||
resetQuizSelection();
|
||||
} else {
|
||||
alert('모든 퀴즈를 완료하셨습니다!');
|
||||
}
|
||||
}
|
||||
|
||||
function resetQuizSelection() {
|
||||
$('.qzSelect a').removeClass('on');
|
||||
}
|
||||
|
||||
function showHintModal(hintUrl) {
|
||||
$.get(hintUrl, function(data) {
|
||||
$('#hintModalContent').html(data);
|
||||
MicroModal.show('hintModal');
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
showHintModal: showHintModal
|
||||
};
|
||||
})();
|
||||
|
||||
$(document).ready(function() {
|
||||
OXQuiz.init();
|
||||
});
|
||||
@@ -0,0 +1,307 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
init();
|
||||
});
|
||||
|
||||
function init() {
|
||||
initStampCardSlider();
|
||||
initModal();
|
||||
loadImages();
|
||||
updateTotalStamps();
|
||||
checkStampStatus();
|
||||
|
||||
// 새로고침 버튼 클릭 이벤트 처리
|
||||
$('.stampCardWrap').on('click', '.btn_reply', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation(); // 슬라이드 이벤트와 충돌 방지
|
||||
var couponIndex = $(this).closest('.stampCard').data('coupon-index');
|
||||
refreshStamps(couponIndex);
|
||||
});
|
||||
}
|
||||
|
||||
function checkStampStatus() {
|
||||
// 데이터가 없는 경우 또는 교환권이 모두 사용된 경우
|
||||
if (screenInfo.totalStamps === 0 || screenInfo.availableExchangeTickets === 0) {
|
||||
// 교환권 화면을 예시 HTML처럼 변경
|
||||
$('.sub-box').html(`
|
||||
<div style="height: 200px; display: flex; justify-content: center; align-items: center; gap: 12px; flex-wrap: wrap;">
|
||||
<button class="btn outline lg fullscreen-trigger" data-micromodal-trigger="modal-1">적립중 스탬프가 없는경우</button>
|
||||
<br><br>
|
||||
<button class="btn outline lg" id="acorn_toast">교환권발급완료</button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
function loadImages() {
|
||||
console.log('Starting to load images');
|
||||
loadImage('reward', screenInfo.rewardImagePath, $('#rewardImage'));
|
||||
}
|
||||
|
||||
function loadImage(imageType, imagePath, $img) {
|
||||
if ($img.length) {
|
||||
$img.attr('src', imagePath);
|
||||
console.log(`${imageType} image loaded successfully`);
|
||||
} else {
|
||||
console.warn(`Image element not found for ${imageType}`);
|
||||
}
|
||||
}
|
||||
|
||||
function initStampCardSlider() {
|
||||
const $stampCardWrap = $('.stampCardWrap');
|
||||
const couponCount = screenInfo.coupons.length;
|
||||
let currentCouponIndex = 0;
|
||||
let startX, moveX;
|
||||
|
||||
// 모든 쿠폰 카드를 미리 생성
|
||||
function createAllCouponCards() {
|
||||
screenInfo.coupons.forEach((coupon, index) => {
|
||||
const $card = createCouponCard(coupon, index);
|
||||
$stampCardWrap.append($card);
|
||||
});
|
||||
|
||||
// 페이지네이션 생성
|
||||
const $pagination = $('<div class="pagination"></div>');
|
||||
for (let i = 0; i < couponCount; i++) {
|
||||
const $button = $(`<button data-index="${i}"></button>`);
|
||||
$pagination.append($button);
|
||||
}
|
||||
$stampCardWrap.append($pagination);
|
||||
}
|
||||
|
||||
function createCouponCard(coupon, index) {
|
||||
return $(`
|
||||
<div class="stampCard" data-coupon-index="${index}" style="display: none;">
|
||||
<div class="stampCardTop">
|
||||
<p class="shopName">
|
||||
<span>${coupon.storeName}</span>
|
||||
<a href="javascript:void(0);" class="btn_reply">새로고침</a>
|
||||
</p>
|
||||
<p class="cardCnt"><b>${coupon.extiketStmpCnt}</b> / 10</p>
|
||||
</div>
|
||||
<ul class="stampArea">
|
||||
${Array(10).fill().map((_, i) => `<li class="${i < coupon.extiketStmpCnt ? 'on' : ''}"><span>${i + 1}</span></li>`).join('')}
|
||||
</ul>
|
||||
<div class="stampCardbm">
|
||||
<p class="useDate">유효기간 ${formatDate(coupon.stmpValidDt)} 까지</p>
|
||||
<p class="giftInfo">스탬프 <b>10개 적립</b>시 이달의 <b>선물 교환권</b>을 드려요.</p>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
function showCouponCard(index) {
|
||||
$('.stampCard').hide();
|
||||
$(`.stampCard[data-coupon-index="${index}"]`).fadeIn(300);
|
||||
$('.pagination button').removeClass('active');
|
||||
$(`.pagination button[data-index="${index}"]`).addClass('active');
|
||||
|
||||
const coupon = screenInfo.coupons[index];
|
||||
if (coupon.extiketStmpCnt === 10 && coupon.exchngAt === 'Y') {
|
||||
showToast('교환권 발급이 완료되었습니다!');
|
||||
}
|
||||
}
|
||||
|
||||
function nextCoupon() {
|
||||
currentCouponIndex = (currentCouponIndex + 1) % couponCount;
|
||||
showCouponCard(currentCouponIndex);
|
||||
}
|
||||
|
||||
function previousCoupon() {
|
||||
currentCouponIndex = (currentCouponIndex - 1 + couponCount) % couponCount;
|
||||
showCouponCard(currentCouponIndex);
|
||||
}
|
||||
|
||||
// 페이지네이션 버튼 이벤트 핸들러
|
||||
$stampCardWrap.on('click', '.pagination button', function(e) {
|
||||
e.stopPropagation(); // 버블링 방지
|
||||
currentCouponIndex = $(this).data('index');
|
||||
showCouponCard(currentCouponIndex);
|
||||
});
|
||||
|
||||
// 전체 영역 클릭 이벤트 핸들러
|
||||
$stampCardWrap.on('click', function(e) {
|
||||
const clickX = e.clientX;
|
||||
const wrapWidth = $stampCardWrap.width();
|
||||
const halfWidth = wrapWidth / 2;
|
||||
|
||||
if (clickX < halfWidth) {
|
||||
previousCoupon();
|
||||
} else {
|
||||
nextCoupon();
|
||||
}
|
||||
});
|
||||
|
||||
// 터치 이벤트 핸들러
|
||||
$stampCardWrap.on('touchstart', function(e) {
|
||||
startX = e.touches[0].clientX;
|
||||
});
|
||||
|
||||
$stampCardWrap.on('touchmove', function(e) {
|
||||
moveX = e.touches[0].clientX;
|
||||
});
|
||||
|
||||
$stampCardWrap.on('touchend', function(e) {
|
||||
if (startX - moveX > 50) {
|
||||
nextCoupon();
|
||||
} else if (moveX - startX > 50) {
|
||||
previousCoupon();
|
||||
}
|
||||
});
|
||||
|
||||
// function startAutoSlide() {
|
||||
// if (isAutoSlideActive) {
|
||||
// interval = setInterval(nextCoupon, 3000);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// function stopAutoSlide() {
|
||||
// clearInterval(interval);
|
||||
// }
|
||||
//
|
||||
// function restartAutoSlide() {
|
||||
// stopAutoSlide();
|
||||
// startAutoSlide();
|
||||
// }
|
||||
|
||||
// 슬라이더 초기화
|
||||
if (couponCount > 0) {
|
||||
createAllCouponCards();
|
||||
showCouponCard(currentCouponIndex);
|
||||
} else {
|
||||
$stampCardWrap.html('<p>사용 가능한 스탬프 카드가 없습니다.</p>');
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
const date = new Date(dateString);
|
||||
return `${date.getFullYear()}.${(date.getMonth() + 1).toString().padStart(2, '0')}.${date.getDate().toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function initModal() {
|
||||
MicroModal.init({
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true,
|
||||
});
|
||||
|
||||
$('.fullscreen-trigger').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var modalId = $(this).attr('data-micromodal-trigger');
|
||||
openModal(modalId);
|
||||
});
|
||||
|
||||
$('.microModal .microModal__close').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 = '';
|
||||
});
|
||||
|
||||
if (window.location.hash) {
|
||||
var modalId = window.location.hash.replace('#', '');
|
||||
openModal(modalId);
|
||||
}
|
||||
}
|
||||
|
||||
function openModal(modalId) {
|
||||
MicroModal.show(modalId, {
|
||||
onShow: function(modal) {
|
||||
if (window.location.hash !== '#' + modalId) {
|
||||
window.history.pushState({ modal: 'open' }, '', '#' + modalId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
document.body.style.overflow = '';
|
||||
MicroModal.close(modalId);
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const $toastPop = $('#modal_exchange_ticket_toast');
|
||||
$toastPop.text(message);
|
||||
$toastPop.addClass('show');
|
||||
setTimeout(() => {
|
||||
$toastPop.removeClass('show');
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function refreshStamps(couponIndex) {
|
||||
const coupon = screenInfo.coupons[couponIndex];
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/refreshStamps',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({
|
||||
bnfInnb: screenInfo.bnfInnb,
|
||||
strInnb: coupon.strInnb,
|
||||
bnfExtiketInnb: coupon.bnfExtiketInnb,
|
||||
mbrInnb: screenInfo.mbrInnb,
|
||||
mbrDvCd: screenInfo.mbrDvCd,
|
||||
sopmalCd: screenInfo.sopmalCd
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
try {
|
||||
const responseBody = JSON.parse(response.resBody.result);
|
||||
const success = responseBody.success;
|
||||
if (success) {
|
||||
updateStampCard(couponIndex, responseBody.cardInfo);
|
||||
showToast('스탬프 정보가 새로고침되었습니다.');
|
||||
} else {
|
||||
showToast(responseBody.message || '스탬프 정보를 새로고침하는데 실패했습니다.');
|
||||
}
|
||||
} catch (error) {
|
||||
showToast('응답을 처리하는 동안 오류가 발생했습니다.');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
showToast('스탬프 정보를 새로고침하는데 실패했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateStampCard(couponIndex, data) {
|
||||
const previousExchngAt = screenInfo.coupons[couponIndex].exchangeable;
|
||||
|
||||
// 새로운 데이터로 coupon 객체 업데이트
|
||||
Object.assign(screenInfo.coupons[couponIndex], data.cardInfo);
|
||||
|
||||
const coupon = screenInfo.coupons[couponIndex];
|
||||
const $card = $(`.stampCard[data-coupon-index="${couponIndex}"]`);
|
||||
|
||||
$card.find('.cardCnt b').text(coupon.extiketStmpCnt);
|
||||
$card.find('.stampArea li').each((index, el) => {
|
||||
$(el).toggleClass('on', index < coupon.extiketStmpCnt);
|
||||
});
|
||||
$card.find('.useDate').text(`유효기간 ${formatDate(coupon.stmpValidDt)} 까지`);
|
||||
$card.find('.shopName span').text(coupon.branchName);
|
||||
|
||||
// 페이드 효과 적용
|
||||
$card.fadeOut(150).fadeIn(150);
|
||||
|
||||
// 교환권 발급 완료 시 토스트 메시지 표시
|
||||
if (coupon.extiketStmpCnt === 10 && coupon.exchangeable === 'Y' && previousExchngAt !== 'Y') {
|
||||
showToast('교환권 발급이 완료되었습니다!');
|
||||
}
|
||||
|
||||
// 전체 스탬프 수 업데이트
|
||||
updateTotalStamps();
|
||||
}
|
||||
|
||||
function updateTotalStamps() {
|
||||
const totalCoupons = screenInfo.coupons.length;
|
||||
$('.card_title b').text(totalCoupons);
|
||||
screenInfo.totalStamps = totalCoupons;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
const QREvent = (function() {
|
||||
let isEligible = false;
|
||||
|
||||
function init() {
|
||||
setupEventListeners();
|
||||
setupModal();
|
||||
checkEligibility();
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
$('#participateEvent').on('click', handleEventParticipation);
|
||||
}
|
||||
|
||||
function setupModal() {
|
||||
MicroModal.init({
|
||||
disableScroll: true,
|
||||
awaitCloseAnimation: true,
|
||||
});
|
||||
|
||||
$('.microModal .microModal__close').on('click', function() {
|
||||
const modalId = $(this).closest('.microModal').attr('id');
|
||||
closeModal(modalId);
|
||||
});
|
||||
}
|
||||
|
||||
function openModal(modalId) {
|
||||
MicroModal.show(modalId);
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
MicroModal.close(modalId);
|
||||
}
|
||||
|
||||
function checkEligibility() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/checkQREvntEligibility',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
isEligible = response.resBody.result.eligible;
|
||||
updateUIBasedOnEligibility();
|
||||
} else {
|
||||
console.error('응모 가능 여부 확인 실패:', response.error);
|
||||
showErrorMessage('응모 가능 여부를 확인하는 중 오류가 발생했습니다.');
|
||||
}
|
||||
},
|
||||
error: handleAjaxError
|
||||
});
|
||||
}
|
||||
|
||||
function updateUIBasedOnEligibility() {
|
||||
const $participateButton = $('#participateEvent');
|
||||
if (isEligible) {
|
||||
$participateButton.prop('disabled', false).text('이벤트 참여하기');
|
||||
} else {
|
||||
$participateButton.prop('disabled', true).text('이미 참여하셨습니다');
|
||||
$('#modalMessage').text('이미 참여하셨거나 응모가 불가능합니다.');
|
||||
openModal('modal-1');
|
||||
}
|
||||
}
|
||||
|
||||
function handleEventParticipation() {
|
||||
if (!isEligible) {
|
||||
openModal('modal-1');
|
||||
return;
|
||||
}
|
||||
|
||||
processWinning();
|
||||
}
|
||||
|
||||
function processWinning() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/processQREvntWinning',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.won) {
|
||||
openModal('modal-2'); // 당첨
|
||||
} else {
|
||||
openModal('modal-3'); // 미당첨
|
||||
}
|
||||
isEligible = false; // 참여 후에는 더 이상 참여 불가능
|
||||
updateUIBasedOnEligibility();
|
||||
} else {
|
||||
showErrorMessage('이벤트 참여 중 오류가 발생했습니다.');
|
||||
}
|
||||
},
|
||||
error: handleAjaxError
|
||||
});
|
||||
}
|
||||
|
||||
function viewCoupon() {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/selectIssuedQREvntCoupon',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
if (result.couponInfo) {
|
||||
updateCouponModal(result.couponInfo);
|
||||
openModal('modal-4'); // 쿠폰 정보 모달
|
||||
} else {
|
||||
showErrorMessage('발급된 쿠폰이 없습니다.');
|
||||
}
|
||||
} else {
|
||||
showErrorMessage('쿠폰 정보 조회 중 오류가 발생했습니다.');
|
||||
}
|
||||
},
|
||||
error: handleAjaxError
|
||||
});
|
||||
}
|
||||
|
||||
function updateCouponModal(couponInfo) {
|
||||
$('#modal-4 .qcNo').text(couponInfo.couponNumber);
|
||||
$('#modal-4 .qcCnt').text(couponInfo.discountAmount);
|
||||
$('#modal-4 .qcTxt02').text(couponInfo.useCondition);
|
||||
$('#modal-4 .qcTxt03').text(couponInfo.validUntil);
|
||||
}
|
||||
|
||||
function handleAjaxError(jqXHR, textStatus, errorThrown) {
|
||||
console.error('Ajax error:', textStatus, errorThrown);
|
||||
showErrorMessage('서버 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
|
||||
function showErrorMessage(message) {
|
||||
alert(message);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
openModal: openModal,
|
||||
viewCoupon: viewCoupon
|
||||
};
|
||||
})();
|
||||
|
||||
function onQRCodeScanned(scanResult) {
|
||||
QREvent.init();
|
||||
$('#participateEvent').click();
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const RouletteGame = {
|
||||
canvas: document.getElementById('rouletteCanvas'),
|
||||
ctx: null,
|
||||
colors: ['#FDBE01', '#ffffff', '#FDBE01', '#ffffff', '#FDBE01', '#ffffff', '#FDBE01', '#ffffff'],
|
||||
angle: 0,
|
||||
segmentAngle: 2 * Math.PI / segments.length,
|
||||
diameterPercentage: 0.76,
|
||||
canvasCenterX: 0,
|
||||
canvasCenterY: 0,
|
||||
radius: 0,
|
||||
isSpinning: false,
|
||||
|
||||
init() {
|
||||
this.ctx = this.canvas.getContext('2d');
|
||||
this.canvasCenterX = this.canvas.width / 2;
|
||||
this.canvasCenterY = this.canvas.height / 2;
|
||||
this.radius = (Math.min(this.canvas.width, this.canvas.height) * this.diameterPercentage) / 2;
|
||||
|
||||
this.addEventListeners();
|
||||
this.drawRoulette();
|
||||
this.loadImages();
|
||||
},
|
||||
|
||||
addEventListeners() {
|
||||
const spinButton = document.getElementById('spinButton');
|
||||
spinButton.addEventListener('click', this.spinRoulette.bind(this));
|
||||
|
||||
const closeButton = document.querySelector('.microModal__btn');
|
||||
closeButton.addEventListener('click', () => MicroModal.close('resultPopup'));
|
||||
},
|
||||
|
||||
drawRoulette() {
|
||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
let angle = this.angle;
|
||||
|
||||
segments.forEach((seg, index) => {
|
||||
this.drawSegment(seg, index, angle);
|
||||
angle += this.segmentAngle;
|
||||
});
|
||||
|
||||
this.drawArrow();
|
||||
},
|
||||
|
||||
drawSegment(seg, index, angle) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.fillStyle = this.colors[index % this.colors.length];
|
||||
this.ctx.moveTo(this.canvasCenterX, this.canvasCenterY);
|
||||
this.ctx.arc(this.canvasCenterX, this.canvasCenterY, this.radius, angle, angle + this.segmentAngle);
|
||||
this.ctx.lineTo(this.canvasCenterX, this.canvasCenterY);
|
||||
this.ctx.fill();
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.translate(this.canvasCenterX, this.canvasCenterY);
|
||||
this.ctx.rotate(angle + this.segmentAngle / 2);
|
||||
this.ctx.textAlign = 'right';
|
||||
this.ctx.fillStyle = '#000000';
|
||||
this.ctx.font = 'bold 20px "GmarketSans"';
|
||||
this.ctx.fillText(seg.label, this.radius - 20, 10);
|
||||
this.ctx.restore();
|
||||
},
|
||||
|
||||
drawArrow() {
|
||||
this.ctx.fillStyle = 'transparent';
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(this.canvasCenterX, this.canvasCenterY - this.radius - 15);
|
||||
this.ctx.lineTo(this.canvasCenterX - 10, this.canvasCenterY - this.radius + 5);
|
||||
this.ctx.lineTo(this.canvasCenterX + 10, this.canvasCenterY - this.radius + 5);
|
||||
this.ctx.closePath();
|
||||
this.ctx.fill();
|
||||
},
|
||||
|
||||
spinRoulette() {
|
||||
if (this.isSpinning) return;
|
||||
|
||||
const remainingChancesElement = document.querySelector('.rouletteCnt b');
|
||||
const remainingChances = parseInt(remainingChancesElement.textContent, 10);
|
||||
|
||||
if (isNaN(remainingChances) || remainingChances <= 0) {
|
||||
alert('남은 횟수가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.isSpinning = true;
|
||||
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/playRougame',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
"mbrInnb": 87626,
|
||||
"bnfDvCd": "040",
|
||||
"bnfInnb": bnfInnb,
|
||||
"mbrDvCd": "GC"
|
||||
}),
|
||||
success: (response) => {
|
||||
const result = JSON.parse(response.resBody.result);
|
||||
const targetRank = result.rank;
|
||||
const targetIndex = segments.findIndex(segment => segment.rank === targetRank);
|
||||
|
||||
if (targetIndex !== -1) {
|
||||
this.startSpin(targetIndex);
|
||||
this.updateRemainingChances();
|
||||
}
|
||||
},
|
||||
error: (xhr, status, error) => {
|
||||
console.error("AJAX request failed:", error);
|
||||
this.isSpinning = false;
|
||||
alert('룰렛 회전 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
startSpin(targetIndex) {
|
||||
const segmentsCount = segments.length;
|
||||
const segmentAngleDeg = 360 / segmentsCount;
|
||||
const targetAngleDeg = targetIndex * segmentAngleDeg + segmentAngleDeg / 2 - 90;
|
||||
const initialAngle = this.angle % (2 * Math.PI);
|
||||
const finalAngle = (targetAngleDeg * Math.PI / 180) + 2 * Math.PI * 5;
|
||||
|
||||
const spinAngleStart = Math.random() * 10 + 10;
|
||||
let spinTime = 0;
|
||||
const spinTimeTotal = Math.random() * 3 + 4 * 1000;
|
||||
|
||||
const rotateWheel = () => {
|
||||
spinTime += 30;
|
||||
if (spinTime >= spinTimeTotal) {
|
||||
this.stopRotateWheel();
|
||||
return;
|
||||
}
|
||||
const spinAngle = this.easeOut(spinTime, 0, finalAngle - initialAngle, spinTimeTotal);
|
||||
this.angle = initialAngle + spinAngle;
|
||||
this.drawRoulette();
|
||||
requestAnimationFrame(rotateWheel);
|
||||
};
|
||||
|
||||
rotateWheel();
|
||||
},
|
||||
|
||||
stopRotateWheel() {
|
||||
const degrees = this.angle * 180 / Math.PI + 90;
|
||||
const arcd = 360 / segments.length;
|
||||
const index = Math.floor((360 - degrees % 360) / arcd);
|
||||
document.getElementById('resultText').textContent = segments[index].label;
|
||||
MicroModal.show('resultPopup');
|
||||
this.isSpinning = false;
|
||||
},
|
||||
|
||||
easeOut(t, b, c, d) {
|
||||
const ts = (t /= d) * t;
|
||||
const tc = ts * t;
|
||||
return b + c * (tc + -3 * ts + 3 * t);
|
||||
},
|
||||
|
||||
updateRemainingChances() {
|
||||
const remainingChancesElement = document.querySelector('.rouletteCnt b');
|
||||
if (remainingChancesElement) {
|
||||
let remainingChances = parseInt(remainingChancesElement.textContent, 10);
|
||||
if (!isNaN(remainingChances) && remainingChances > 0) {
|
||||
remainingChancesElement.textContent = remainingChances - 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
loadImages() {
|
||||
const representativeImage = document.querySelector('.rouletteImg img');
|
||||
if (representativeImage) {
|
||||
this.loadImage('representative', screenInfo.representativeImagePath, $(representativeImage));
|
||||
}
|
||||
},
|
||||
|
||||
loadImage(imageType, imagePath, $img) {
|
||||
if (!imagePath) {
|
||||
console.warn(`Image path for ${imageType} is not available`);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($img.length) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/image',
|
||||
method: 'GET',
|
||||
data: { path: imagePath },
|
||||
xhrFields: { responseType: 'blob' },
|
||||
success: function(data) {
|
||||
const imageUrl = URL.createObjectURL(data);
|
||||
$img.attr('src', imageUrl);
|
||||
console.log(`${imageType} image loaded successfully`);
|
||||
},
|
||||
error: function() {
|
||||
console.error(`Failed to load ${imageType} image`);
|
||||
$img.attr('src', '/path/to/fallback-image.jpg');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(`Image element not found for ${imageType}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RouletteGame.init();
|
||||
});
|
||||
21
build/resources/main/static/sopmall/mobile/js/bnft/stepcnt/Chart.bundle.min.js
vendored
Normal file
21
build/resources/main/static/sopmall/mobile/js/bnft/stepcnt/Chart.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,278 @@
|
||||
//만보기달력 추가 encomms
|
||||
function loadImages() {
|
||||
console.log('이미지 로딩 시작');
|
||||
loadImage('representative', screenInfo.representativeImagePath, $('#representativeImage'));
|
||||
loadImage('reward', screenInfo.rewardImagePath, $('.product_img img'));
|
||||
}
|
||||
|
||||
function loadImage(imageType, imagePath, $img) {
|
||||
if (!imagePath) {
|
||||
console.warn(`${imageType} 이미지 경로가 없습니다`);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($img.length) {
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/image',
|
||||
method: 'GET',
|
||||
data: { path: imagePath, type: imageType },
|
||||
xhrFields: { responseType: 'blob' },
|
||||
success: function(data) {
|
||||
const imageUrl = URL.createObjectURL(data);
|
||||
$img.attr('src', imageUrl);
|
||||
console.log(`${imageType} 이미지 로드 성공`);
|
||||
|
||||
if (imageType === 'reward') {
|
||||
updateRewardLink();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
console.error(`${imageType} 이미지 로드 실패`);
|
||||
$img.attr('src', '/path/to/fallback-image.jpg');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(`${imageType} 이미지 요소를 찾을 수 없습니다`);
|
||||
}
|
||||
}
|
||||
|
||||
function updateRewardLink() {
|
||||
const $rewardLink = $('.stepStampBox2 a');
|
||||
if ($rewardLink.length && screenInfo.scrRwdLinkUrl) {
|
||||
$rewardLink.attr('href', screenInfo.scrRwdLinkUrl);
|
||||
console.log('보상 링크 URL 업데이트:', screenInfo.scrRwdLinkUrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
loadImages();
|
||||
|
||||
const daysContainer = document.querySelector(".stepDays");
|
||||
const daysInMonth = 31; // May 2024 has 31 days
|
||||
const currentDate = new Date();
|
||||
let currentDay = currentDate.getDate();
|
||||
const firstDayOfMonth = new Date(2024, 4, 1).getDay(); // May is the 5th month (zero-based index)
|
||||
|
||||
// 만보기 데이터를 임의로 생성 (예: 각 날마다 무작위 값)
|
||||
const stepsData = Array.from({ length: daysInMonth }, () => Math.floor(Math.random() * 20000));
|
||||
|
||||
// Generate empty cells for the days before the first day of the month
|
||||
for (let i = 0; i < firstDayOfMonth; i++) {
|
||||
const emptyCell = document.createElement("div");
|
||||
daysContainer.appendChild(emptyCell);
|
||||
}
|
||||
|
||||
// Generate calendar days
|
||||
for (let day = 1; day <= daysInMonth; day++) {
|
||||
const calendarDay = document.createElement("div");
|
||||
calendarDay.textContent = day;
|
||||
|
||||
// Add 'today' class to the current date
|
||||
if (day === currentDay) {
|
||||
calendarDay.classList.add("today");
|
||||
}
|
||||
|
||||
// 만보기 숫자 기능 추가
|
||||
const stepsCount = document.createElement("div");
|
||||
stepsCount.textContent = `${stepsData[day - 1] || 0}`; // steps 텍스트 제거
|
||||
stepsCount.classList.add("steps"); // Add 'steps' class to the steps count element
|
||||
calendarDay.appendChild(stepsCount);
|
||||
|
||||
// 만 보가 넘으면 success 클래스를 추가
|
||||
if (stepsData[day - 1] > 10000) {
|
||||
calendarDay.classList.add("success");
|
||||
}
|
||||
|
||||
// 7500 보가 넘으면 success3 클래스를 추가
|
||||
if (stepsData[day - 1] >= 7500 && stepsData[day - 1] < 10000) {
|
||||
calendarDay.classList.add("success2");
|
||||
}
|
||||
|
||||
// 5000 보가 넘으면 success 클래스를 추가
|
||||
if (stepsData[day - 1] >= 5000 && stepsData[day - 1] < 7500) {
|
||||
calendarDay.classList.add("success2");
|
||||
}
|
||||
|
||||
// 2500 보가 넘으면 success 클래스를 추가
|
||||
if (stepsData[day - 1] >= 2500 && stepsData[day - 1] < 5000) {
|
||||
calendarDay.classList.add("success2");
|
||||
}
|
||||
|
||||
daysContainer.appendChild(calendarDay);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//만보기 도넛차트
|
||||
// round corners
|
||||
Chart.pluginService.register({
|
||||
afterUpdate: function(chart) {
|
||||
if (chart.config.options.elements.arc.roundedCornersFor !== undefined) {
|
||||
var arc = chart.getDatasetMeta(0).data[chart.config.options.elements.arc.roundedCornersFor];
|
||||
arc.round = {
|
||||
x: (chart.chartArea.left + chart.chartArea.right) / 2,
|
||||
y: (chart.chartArea.top + chart.chartArea.bottom) / 2,
|
||||
radius: (chart.outerRadius + chart.innerRadius) / 2,
|
||||
thickness: (chart.outerRadius - chart.innerRadius) / 2 - 1,
|
||||
backgroundColor: arc._model.backgroundColor
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
afterDraw: function(chart) {
|
||||
if (chart.config.options.elements.arc.roundedCornersFor !== undefined) {
|
||||
var ctx = chart.chart.ctx;
|
||||
var arc = chart.getDatasetMeta(0).data[chart.config.options.elements.arc.roundedCornersFor];
|
||||
var startAngle = Math.PI / 2 - arc._view.startAngle;
|
||||
var endAngle = Math.PI / 2 - arc._view.endAngle;
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(arc.round.x, arc.round.y);
|
||||
console.log(arc.round.startAngle)
|
||||
ctx.fillStyle = arc.round.backgroundColor;
|
||||
ctx.beginPath();
|
||||
ctx.arc(arc.round.radius * Math.sin(startAngle), arc.round.radius * Math.cos(startAngle), arc.round.thickness, 0, 2 * Math.PI);
|
||||
ctx.arc(arc.round.radius * Math.sin(endAngle), arc.round.radius * Math.cos(endAngle), arc.round.thickness, 0, 2 * Math.PI);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// write text plugin
|
||||
Chart.pluginService.register({
|
||||
afterUpdate: function(chart) {
|
||||
if (chart.config.options.elements.center) {
|
||||
var helpers = Chart.helpers;
|
||||
var centerConfig = chart.config.options.elements.center;
|
||||
var globalConfig = Chart.defaults.global;
|
||||
var ctx = chart.chart.ctx;
|
||||
|
||||
var fontStyle = helpers.getValueOrDefault(centerConfig.fontStyle, globalConfig.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(centerConfig.fontFamily, globalConfig.defaultFontFamily);
|
||||
|
||||
if (centerConfig.fontSize)
|
||||
var fontSize = centerConfig.fontSize;
|
||||
// figure out the best font size, if one is not specified
|
||||
else {
|
||||
ctx.save();
|
||||
var fontSize = helpers.getValueOrDefault(centerConfig.minFontSize, 1);
|
||||
var maxFontSize = helpers.getValueOrDefault(centerConfig.maxFontSize, 256);
|
||||
var maxText = helpers.getValueOrDefault(centerConfig.maxText, centerConfig.text);
|
||||
|
||||
do {
|
||||
ctx.font = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
var textWidth = ctx.measureText(maxText).width;
|
||||
|
||||
// check if it fits, is within configured limits and that we are not simply toggling back and forth
|
||||
if (textWidth < chart.innerRadius * 2 && fontSize < maxFontSize)
|
||||
fontSize += 1;
|
||||
else {
|
||||
// reverse last step
|
||||
fontSize -= 1;
|
||||
break;
|
||||
}
|
||||
} while (true)
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// save properties
|
||||
chart.center = {
|
||||
font: helpers.fontString(fontSize, fontStyle, fontFamily),
|
||||
fillStyle: helpers.getValueOrDefault(centerConfig.fontColor, globalConfig.defaultFontColor)
|
||||
};
|
||||
}
|
||||
},
|
||||
afterDraw: function(chart) {
|
||||
if (chart.center) {
|
||||
var centerConfig = chart.config.options.elements.center;
|
||||
var ctx = chart.chart.ctx;
|
||||
|
||||
ctx.save();
|
||||
ctx.font = chart.center.font;
|
||||
ctx.fillStyle = chart.center.fillStyle;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
var centerX = (chart.chartArea.left + chart.chartArea.right) / 2;
|
||||
var centerY = (chart.chartArea.top + chart.chartArea.bottom) / 2;
|
||||
ctx.fillText(centerConfig.text, centerX, centerY);
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
var config = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: [
|
||||
"오늘 걸은 걸음",
|
||||
"목표 달성까지"
|
||||
],
|
||||
datasets: [{
|
||||
data: [67, 33],
|
||||
backgroundColor: [
|
||||
"#78b857",
|
||||
"#d9d9d9"
|
||||
],
|
||||
hoverBackgroundColor: [
|
||||
"#78b857",
|
||||
"#d9d9d9"
|
||||
]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
elements: {
|
||||
arc: {
|
||||
roundedCornersFor: 0
|
||||
},
|
||||
center: {
|
||||
// the longest text that could appear in the center
|
||||
maxText: '100%',
|
||||
text: '60%',
|
||||
fontColor: '#000',
|
||||
fontFamily: "'GmarketSans', 'Arial', sans-serif",
|
||||
fontStyle: 'bold',
|
||||
fontSize: 20,
|
||||
// if a fontSize is NOT specified, we will scale (within the below limits) maxText to take up the maximum space in the center
|
||||
// if these are not specified either, we default to 1 and 256
|
||||
minFontSize: 1,
|
||||
maxFontSize: 256,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var ctx = document.getElementById("myChart").getContext("2d");
|
||||
var myChart = new Chart(ctx, config);
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
// 토글 상태 변경 이벤트 리스너 설정
|
||||
$('#stepcntToggle').change(function() {
|
||||
var isChecked = $(this).is(':checked');
|
||||
var status = isChecked ? 'Y' : 'N';
|
||||
|
||||
// AJAX 요청 보내기
|
||||
$.ajax({
|
||||
url: '/sopmal/bnft/insertStepcntAgreement', // 서버의 엔드포인트 URL
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
agreAt: status
|
||||
// 필요한 추가 데이터가 있으면 여기에 추가
|
||||
}),
|
||||
success: function(response) {
|
||||
console.log('Success:', response);
|
||||
// 성공 시 추가 작업 (알림 표시 등)
|
||||
},
|
||||
error: function(error) {
|
||||
console.error('Error:', error);
|
||||
// 실패 시 추가 작업 (알림 표시 등)
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user