/**
* 커스텀 팝업 관리 스크립트
* - ShopbySkin API에서 팝업 데이터를 불러와 지정된 popupNo만 오버레이로 표시
* - 오늘 하루 안보기 기능 (로컬스토리지, 팝업별)
* - fade in 애니메이션
* - 딤 배경 하나에 여러 팝업 겹쳐서 표시
*/
(() => {
const { EventManager, actions } = ShopbySkin;
// 커스텀 팝업으로 표시할 popupId 목록 (popupId가 null이 아닌 팝업 중 이 배열에 포함된 것만 커스텀 렌더링)
const CUSTOM_POPUP_IDS = ['BIG-POP-PC'];
const STORAGE_KEY_PREFIX = 'CUSTOM_POPUP_NO_SHOW_';
const NOW = new Date();
/**
* 오늘 날짜 문자열 반환 (YYYY-MM-DD)
*/
const getTodayString = () => {
const year = NOW.getFullYear();
const month = String(NOW.getMonth() + 1).padStart(2, '0');
const day = String(NOW.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
};
/**
* 특정 팝업의 오늘 하루 안보기 체크
*/
const shouldHideToday = (popupNo) => {
const savedDate = localStorage.getItem(`${STORAGE_KEY_PREFIX}${popupNo}`);
return savedDate === getTodayString();
};
/**
* 특정 팝업 오늘 하루 안보기 저장
*/
const setNoShowToday = (popupNo) => {
localStorage.setItem(`${STORAGE_KEY_PREFIX}${popupNo}`, getTodayString());
};
/**
* 팝업 콘텐츠 렌더링 (여러 개 겹쳐서 표시)
*/
const renderPopups = (popups) => {
const contentArea = document.getElementById('customPopupContent');
if (!contentArea) return;
contentArea.innerHTML = '';
popups.forEach((popup) => {
const wrapper = document.createElement('div');
wrapper.className = 'custom-popup-item';
wrapper.setAttribute('data-popup-no', popup.popupNo);
wrapper.innerHTML = `
${popup.content}
`;
contentArea.appendChild(wrapper);
});
};
/**
* 팝업 표시 (애니메이션 포함)
*/
const showPopup = () => {
const overlay = document.querySelector('.custom-popup-overlay');
if (!overlay) return;
overlay.style.display = 'flex';
document.body.style.overflow = 'hidden';
requestAnimationFrame(() => {
requestAnimationFrame(() => {
overlay.classList.add('active');
});
});
};
/**
* 개별 팝업 닫기
*/
const closePopupItem = (popupNo) => {
const item = document.querySelector(`.custom-popup-item[data-popup-no="${popupNo}"]`);
if (item) {
item.style.display = 'none';
}
// 모든 팝업이 닫혔으면 오버레이도 닫기
checkAllPopupsClosed();
};
/**
* 오버레이 전체 닫기 (애니메이션 포함)
*/
const closeOverlay = () => {
const overlay = document.querySelector('.custom-popup-overlay');
if (!overlay) return;
overlay.classList.remove('active');
setTimeout(() => {
overlay.style.display = 'none';
document.body.style.overflow = '';
}, 300);
};
/**
* 모든 팝업이 닫혔는지 확인
*/
const checkAllPopupsClosed = () => {
const allItems = document.querySelectorAll('.custom-popup-item');
const visibleItems = Array.from(allItems).filter((item) => item.style.display !== 'none');
if (visibleItems.length === 0) {
closeOverlay();
}
};
/**
* 이벤트 바인딩
*/
const bindEvents = () => {
document.addEventListener('click', (e) => {
const action = e.target.dataset.action;
const popupNo = e.target.dataset.popupNo;
if (action === 'NO_SHOW_TODAY' && popupNo) {
setNoShowToday(popupNo);
closePopupItem(popupNo);
return;
}
if (action === 'CLOSE' && popupNo) {
closePopupItem(popupNo);
return;
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeOverlay();
}
});
};
/**
* 커스텀 팝업 대상 필터링
* - popupId가 null이 아니고
* - CUSTOM_POPUP_IDS 배열에 포함되어 있으며
* - NORMAL 디자인 타입이고 (MULTI 제외)
* - 오늘 하루 안보기 처리되지 않은 팝업만
*/
const filterTargetPopups = (popups) => {
return popups.filter((popup) => {
if (!popup.popupId) return false;
if (!CUSTOM_POPUP_IDS.includes(popup.popupId)) return false;
if (popup.popupDesignType !== 'NORMAL') return false;
if (shouldHideToday(popup.popupNo)) return false;
return true;
});
};
/**
* 실제 팝업 데이터 API 호출
* - ShopbySkin.actions.getDisplayPopups(): /display/popups API 호출
* - 오늘하루 안보기 처리된 팝업은 자동 제외됨
*/
const fetchPopups = async () => {
try {
const { data } = await actions.getDisplayPopups();
return data || [];
} catch (e) {
console.error('[custom-popup] 팝업 API 호출 실패:', e);
return [];
}
};
/**
* 초기화
*/
const init = async () => {
if (CUSTOM_POPUP_IDS.length === 0) return;
const popups = await fetchPopups();
const targetPopups = filterTargetPopups(popups);
if (targetPopups.length === 0) return;
renderPopups(targetPopups);
bindEvents();
showPopup();
};
// 페이지 로드 완료 시 실행
EventManager.on('PAGE_LOAD_COMPLETED', init);
})();