333 lines
12 KiB
JavaScript
333 lines
12 KiB
JavaScript
function initSurveyListModule(moduleId) {
|
|
const moduleElement = document.getElementById(moduleId);
|
|
if (!moduleElement || moduleElement.classList.contains('initialized')) return;
|
|
|
|
const surveySection = moduleElement.querySelector('.survey-section');
|
|
const surveyGrid = moduleElement.querySelector('.survey-grid');
|
|
const modal = moduleElement.querySelector('.survey-modal');
|
|
const modalOverlay = modal.querySelector('.modal-overlay');
|
|
const modalClose = modal.querySelector('.modal-close');
|
|
const modalTitle = modal.querySelector('.modal-title');
|
|
const modalAuthor = modal.querySelector('.modal-author');
|
|
const modalDeadline = modal.querySelector('.modal-deadline');
|
|
const modalDescription = modal.querySelector('.modal-description');
|
|
const questionsCount = modal.querySelector('.questions-count');
|
|
const participantsCount = modal.querySelector('.participants-count');
|
|
const estimatedTime = modal.querySelector('.estimated-time');
|
|
const progressFill = modal.querySelector('.progress-fill');
|
|
const progressText = modal.querySelector('.progress-text');
|
|
const btnParticipate = modal.querySelector('.modal-footer .btn-participate');
|
|
const btnCancel = modal.querySelector('.btn-cancel');
|
|
|
|
// 설문 데이터 가져오기
|
|
const surveysData = JSON.parse(surveySection.dataset.surveys || '[]');
|
|
|
|
// 설문 카드 렌더링
|
|
function renderSurveyCards() {
|
|
if (!surveysData.length) return;
|
|
|
|
const cardsHTML = surveysData.map(survey => `
|
|
<div class="survey-card" data-survey-id="${survey.id}" style="--theme-color: ${survey.theme_color}">
|
|
<div class="survey-card-header">
|
|
<h3 class="survey-title">${survey.title}</h3>
|
|
${survey.description ? `<p class="survey-description">${survey.description}</p>` : ''}
|
|
</div>
|
|
|
|
<div class="survey-meta">
|
|
<span><i class="fa fa-calendar"></i> ${survey.days_left}일 남음</span>
|
|
<span><i class="fa fa-user"></i> ${survey.created_by}</span>
|
|
</div>
|
|
|
|
<div class="survey-stats">
|
|
<div class="stat-item">
|
|
<i class="fa fa-question-circle"></i>
|
|
<span>${survey.questions_count}개 질문</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<i class="fa fa-users"></i>
|
|
<span>${formatNumber(survey.response_count)}명 참여</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<i class="fa fa-clock"></i>
|
|
<span>약 ${survey.questions_count}분</span>
|
|
</div>
|
|
</div>
|
|
|
|
${survey.max_responses ? `
|
|
<div class="survey-progress">
|
|
<div class="progress-bar">
|
|
<div class="progress-fill" style="width: ${survey.progress}%"></div>
|
|
</div>
|
|
<div class="progress-text">
|
|
${formatNumber(survey.response_count)} / ${formatNumber(survey.max_responses)}명
|
|
</div>
|
|
</div>
|
|
` : ''}
|
|
|
|
<div class="survey-actions">
|
|
<button class="btn-participate" data-survey-id="${survey.id}">
|
|
<i class="fa fa-play"></i> 참여하기
|
|
</button>
|
|
<button class="btn-share" data-survey-id="${survey.id}" data-title="${survey.title}">
|
|
<i class="fa fa-share"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
|
|
surveyGrid.innerHTML = cardsHTML;
|
|
}
|
|
|
|
// 모달 열기
|
|
function openModal(surveyId) {
|
|
const survey = surveysData.find(s => s.id == surveyId);
|
|
if (!survey) return;
|
|
|
|
// 모달 내용 업데이트
|
|
modalTitle.textContent = survey.title;
|
|
modalAuthor.textContent = survey.created_by;
|
|
modalDeadline.textContent = `${survey.days_left}일 남음`;
|
|
modalDescription.textContent = survey.description || '설문에 대한 설명이 없습니다.';
|
|
questionsCount.textContent = `${survey.questions_count}개`;
|
|
participantsCount.textContent = `${formatNumber(survey.response_count)}명`;
|
|
estimatedTime.textContent = `${survey.questions_count}분`;
|
|
|
|
// 진행률 업데이트
|
|
if (survey.max_responses) {
|
|
progressFill.style.width = `${survey.progress}%`;
|
|
progressText.textContent = `${formatNumber(survey.response_count)} / ${formatNumber(survey.max_responses)}명 참여`;
|
|
modal.querySelector('.progress-section').style.display = 'block';
|
|
} else {
|
|
modal.querySelector('.progress-section').style.display = 'none';
|
|
}
|
|
|
|
// 참여하기 버튼 링크 설정
|
|
btnParticipate.href = `${window.location.origin}/theme/rd.lwd/survey_page.php?sv_id=${survey.id}`;
|
|
|
|
// 모달 표시
|
|
modal.classList.add('show');
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
|
|
// 모달 닫기
|
|
function closeModal() {
|
|
modal.classList.remove('show');
|
|
document.body.style.overflow = '';
|
|
}
|
|
|
|
// 설문 공유
|
|
function shareSurvey(surveyId, title) {
|
|
const url = `${window.location.origin}/theme/rd.lwd/rb.custom/survey_form/survey_page.php?sv_id=${surveyId}`;
|
|
|
|
if (navigator.share) {
|
|
// Web Share API 지원시
|
|
navigator.share({
|
|
title: title,
|
|
text: '설문에 참여해보세요!',
|
|
url: url
|
|
}).catch(err => {
|
|
console.log('공유 취소:', err);
|
|
});
|
|
} else {
|
|
// 클립보드에 복사
|
|
if (navigator.clipboard) {
|
|
navigator.clipboard.writeText(url).then(() => {
|
|
showNotification('설문 링크가 클립보드에 복사되었습니다!', 'success');
|
|
}).catch(() => {
|
|
// 클립보드 복사 실패시 프롬프트로 표시
|
|
prompt('설문 링크를 복사하세요:', url);
|
|
});
|
|
} else {
|
|
// 클립보드 API 미지원시 프롬프트로 표시
|
|
prompt('설문 링크를 복사하세요:', url);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 알림 표시
|
|
function showNotification(message, type = 'info') {
|
|
const notification = document.createElement('div');
|
|
notification.className = `survey-notification survey-notification-${type}`;
|
|
notification.innerHTML = `
|
|
<div class="notification-content">
|
|
<i class="fa fa-${type === 'success' ? 'check-circle' : 'info-circle'}"></i>
|
|
<span>${message}</span>
|
|
</div>
|
|
`;
|
|
|
|
// 스타일 추가
|
|
notification.style.cssText = `
|
|
position: fixed;
|
|
top: 20px;
|
|
right: 20px;
|
|
background: ${type === 'success' ? '#28a745' : '#17a2b8'};
|
|
color: white;
|
|
padding: 15px 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
|
z-index: 1060;
|
|
animation: slideInRight 0.3s ease;
|
|
`;
|
|
|
|
document.body.appendChild(notification);
|
|
|
|
setTimeout(() => {
|
|
notification.style.animation = 'slideOutRight 0.3s ease';
|
|
setTimeout(() => {
|
|
notification.remove();
|
|
}, 300);
|
|
}, 3000);
|
|
}
|
|
|
|
// 숫자 포맷팅
|
|
function formatNumber(num) {
|
|
return new Intl.NumberFormat('ko-KR').format(num);
|
|
}
|
|
|
|
// 이벤트 리스너 등록
|
|
function bindEvents() {
|
|
// 설문 카드 클릭 (모달 열기)
|
|
surveyGrid.addEventListener('click', (e) => {
|
|
const card = e.target.closest('.survey-card');
|
|
if (card && !e.target.closest('.survey-actions')) {
|
|
const surveyId = card.dataset.surveyId;
|
|
openModal(surveyId);
|
|
}
|
|
});
|
|
|
|
// 참여하기 버튼 클릭
|
|
surveyGrid.addEventListener('click', (e) => {
|
|
if (e.target.closest('.btn-participate')) {
|
|
e.stopPropagation();
|
|
const surveyId = e.target.closest('.btn-participate').dataset.surveyId;
|
|
window.location.href = `${window.location.origin}/theme/rd.lwd/rb.custom/survey_form/survey_page.php?sv_id=${surveyId}`;
|
|
}
|
|
});
|
|
|
|
// 공유 버튼 클릭
|
|
surveyGrid.addEventListener('click', (e) => {
|
|
if (e.target.closest('.btn-share')) {
|
|
e.stopPropagation();
|
|
const shareBtn = e.target.closest('.btn-share');
|
|
const surveyId = shareBtn.dataset.surveyId;
|
|
const title = shareBtn.dataset.title;
|
|
shareSurvey(surveyId, title);
|
|
}
|
|
});
|
|
|
|
// 모달 닫기 이벤트
|
|
modalClose.addEventListener('click', closeModal);
|
|
btnCancel.addEventListener('click', closeModal);
|
|
modalOverlay.addEventListener('click', closeModal);
|
|
|
|
// ESC 키로 모달 닫기
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Escape' && modal.classList.contains('show')) {
|
|
closeModal();
|
|
}
|
|
});
|
|
|
|
// 카드 호버 효과
|
|
surveyGrid.addEventListener('mouseenter', (e) => {
|
|
const card = e.target.closest('.survey-card');
|
|
if (card) {
|
|
const themeColor = card.style.getPropertyValue('--theme-color') || '#AA20FF';
|
|
card.style.setProperty('--survey-primary', themeColor);
|
|
}
|
|
}, true);
|
|
}
|
|
|
|
// 스크롤 애니메이션
|
|
function initScrollAnimation() {
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.style.animationPlayState = 'running';
|
|
}
|
|
});
|
|
}, {
|
|
threshold: 0.1,
|
|
rootMargin: '0px 0px -50px 0px'
|
|
});
|
|
|
|
// 카드들에 애니메이션 적용
|
|
setTimeout(() => {
|
|
const cards = surveyGrid.querySelectorAll('.survey-card');
|
|
cards.forEach((card, index) => {
|
|
card.style.animationDelay = `${index * 0.1}s`;
|
|
card.style.animationPlayState = 'paused';
|
|
observer.observe(card);
|
|
});
|
|
}, 100);
|
|
}
|
|
|
|
// 진행률 바 애니메이션
|
|
function animateProgressBars() {
|
|
const progressBars = surveyGrid.querySelectorAll('.progress-fill');
|
|
progressBars.forEach(bar => {
|
|
const width = bar.style.width;
|
|
bar.style.width = '0%';
|
|
setTimeout(() => {
|
|
bar.style.width = width;
|
|
}, 500);
|
|
});
|
|
}
|
|
|
|
// 초기화
|
|
function init() {
|
|
renderSurveyCards();
|
|
bindEvents();
|
|
initScrollAnimation();
|
|
|
|
// 진행률 바 애니메이션 (약간의 지연 후)
|
|
setTimeout(animateProgressBars, 800);
|
|
|
|
moduleElement.classList.add('initialized');
|
|
}
|
|
|
|
// 모듈 초기화 실행
|
|
init();
|
|
}
|
|
|
|
// 추가 CSS 애니메이션 (JavaScript로 동적 추가)
|
|
const additionalStyles = `
|
|
@keyframes slideInRight {
|
|
from {
|
|
transform: translateX(100%);
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
transform: translateX(0);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes slideOutRight {
|
|
from {
|
|
transform: translateX(0);
|
|
opacity: 1;
|
|
}
|
|
to {
|
|
transform: translateX(100%);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
.survey-notification .notification-content {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.survey-notification i {
|
|
font-size: 1.2em;
|
|
}
|
|
`;
|
|
|
|
// 스타일 추가 (한 번만)
|
|
if (!document.getElementById('survey-list-module-styles')) {
|
|
const styleSheet = document.createElement('style');
|
|
styleSheet.id = 'survey-list-module-styles';
|
|
styleSheet.textContent = additionalStyles;
|
|
document.head.appendChild(styleSheet);
|
|
} |