first commit 2
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* 통계 페이지 JavaScript
|
||||
*/
|
||||
|
||||
// 전역 변수
|
||||
let responseChart;
|
||||
|
||||
// 페이지 로드 시 초기화
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 데이터가 로드될 때까지 대기
|
||||
if (typeof window.statisticsData !== 'undefined') {
|
||||
initStatistics();
|
||||
} else {
|
||||
// 데이터 로드 대기
|
||||
setTimeout(() => {
|
||||
if (typeof window.statisticsData !== 'undefined') {
|
||||
initStatistics();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
function initStatistics() {
|
||||
// 차트 초기화
|
||||
initResponseChart();
|
||||
initQuestionCharts();
|
||||
|
||||
// 차트 타입 변경 이벤트
|
||||
initChartControls();
|
||||
|
||||
// 숫자 애니메이션 실행
|
||||
setTimeout(animateNumbers, 500);
|
||||
}
|
||||
|
||||
// 응답 현황 차트 초기화
|
||||
function initResponseChart() {
|
||||
const ctx = document.getElementById('responseChart');
|
||||
if (!ctx || !window.statisticsData) return;
|
||||
|
||||
const dailyData = window.statisticsData.chartData.daily;
|
||||
|
||||
// 일별 데이터 준비 (최근 30일)
|
||||
const dailyLabels = [];
|
||||
const dailyValues = [];
|
||||
|
||||
for (let i = 29; i >= 0; i--) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - i);
|
||||
const dateStr = date.toISOString().split('T')[0];
|
||||
const label = date.toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' });
|
||||
|
||||
dailyLabels.push(label);
|
||||
dailyValues.push(dailyData[dateStr] || 0);
|
||||
}
|
||||
|
||||
responseChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: dailyLabels,
|
||||
datasets: [{
|
||||
label: '일별 응답 수',
|
||||
data: dailyValues,
|
||||
borderColor: '#AA20FF',
|
||||
backgroundColor: 'rgba(170, 32, 255, 0.1)',
|
||||
borderWidth: 3,
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
stepSize: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 응답 차트 업데이트
|
||||
function updateResponseChart(type) {
|
||||
if (!responseChart || !window.statisticsData) return;
|
||||
|
||||
const dailyData = window.statisticsData.chartData.daily;
|
||||
const hourlyData = window.statisticsData.chartData.hourly;
|
||||
|
||||
if (type === 'hourly') {
|
||||
// 시간대별 데이터 준비
|
||||
const hourlyLabels = [];
|
||||
const hourlyValues = [];
|
||||
|
||||
for (let i = 0; i < 24; i++) {
|
||||
hourlyLabels.push(i + '시');
|
||||
hourlyValues.push(hourlyData[i] || 0);
|
||||
}
|
||||
|
||||
responseChart.data.labels = hourlyLabels;
|
||||
responseChart.data.datasets[0].data = hourlyValues;
|
||||
responseChart.data.datasets[0].label = '시간대별 응답 수';
|
||||
responseChart.options.scales.x.title = { display: true, text: '시간' };
|
||||
} else {
|
||||
// 일별 데이터로 복원
|
||||
const dailyLabels = [];
|
||||
const dailyValues = [];
|
||||
|
||||
for (let i = 29; i >= 0; i--) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - i);
|
||||
const dateStr = date.toISOString().split('T')[0];
|
||||
const label = date.toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' });
|
||||
|
||||
dailyLabels.push(label);
|
||||
dailyValues.push(dailyData[dateStr] || 0);
|
||||
}
|
||||
|
||||
responseChart.data.labels = dailyLabels;
|
||||
responseChart.data.datasets[0].data = dailyValues;
|
||||
responseChart.data.datasets[0].label = '일별 응답 수';
|
||||
responseChart.options.scales.x.title = { display: true, text: '날짜' };
|
||||
}
|
||||
|
||||
responseChart.update();
|
||||
}
|
||||
|
||||
// 질문별 차트 초기화
|
||||
function initQuestionCharts() {
|
||||
// PHP에서 전달된 질문 데이터를 기반으로 차트 생성
|
||||
// 이 부분은 PHP에서 JavaScript로 데이터를 전달받아 처리
|
||||
}
|
||||
|
||||
// 차트 컨트롤 이벤트
|
||||
function initChartControls() {
|
||||
document.querySelectorAll('.chart-btn').forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
document.querySelectorAll('.chart-btn').forEach(b => b.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
|
||||
const chartType = this.dataset.chart;
|
||||
updateResponseChart(chartType);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 숫자 애니메이션
|
||||
function animateNumbers() {
|
||||
document.querySelectorAll('.stat-number').forEach(element => {
|
||||
const target = parseInt(element.textContent.replace(/,/g, ''));
|
||||
let current = 0;
|
||||
const increment = target / 50;
|
||||
const timer = setInterval(() => {
|
||||
current += increment;
|
||||
if (current >= target) {
|
||||
current = target;
|
||||
clearInterval(timer);
|
||||
}
|
||||
element.textContent = Math.floor(current).toLocaleString('ko-KR');
|
||||
}, 20);
|
||||
});
|
||||
}
|
||||
|
||||
// 인쇄 기능
|
||||
function printStatistics() {
|
||||
if (!window.statisticsData) return;
|
||||
|
||||
const printWindow = window.open('', '_blank');
|
||||
const data = window.statisticsData;
|
||||
|
||||
const printContent = `
|
||||
<html>
|
||||
<head>
|
||||
<title>설문 통계 - ${data.survey.title}</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
.header { text-align: center; margin-bottom: 30px; }
|
||||
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 30px; }
|
||||
.stat-item { text-align: center; padding: 15px; border: 1px solid #ddd; }
|
||||
.stat-number { font-size: 2em; font-weight: bold; color: #AA20FF; }
|
||||
.question { margin-bottom: 30px; page-break-inside: avoid; }
|
||||
.question-title { font-size: 1.2em; font-weight: bold; margin-bottom: 15px; }
|
||||
.answer-item { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee; }
|
||||
@media print { .no-print { display: none; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>설문 통계</h1>
|
||||
<h2>${data.survey.title}</h2>
|
||||
<p>생성일: ${new Date().toLocaleDateString('ko-KR')}</p>
|
||||
</div>
|
||||
|
||||
<div class="stat-grid">
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">${data.stats.totalResponses}</div>
|
||||
<div>완료된 응답</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">${data.stats.completionRate}%</div>
|
||||
<div>완료율</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">${data.stats.avgResponseTime}분</div>
|
||||
<div>평균 응답시간</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">${data.stats.startedResponses}</div>
|
||||
<div>진행중인 응답</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${document.querySelector('.questions-stats') ? document.querySelector('.questions-stats').innerHTML : ''}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
printWindow.document.write(printContent);
|
||||
printWindow.document.close();
|
||||
printWindow.print();
|
||||
}
|
||||
|
||||
// 차트 생성 헬퍼 함수
|
||||
function createQuestionChart(canvasId, chartData, chartType = 'doughnut') {
|
||||
const ctx = document.getElementById(canvasId);
|
||||
if (!ctx) return;
|
||||
|
||||
const colorPalette = ['#AA20FF', '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8'];
|
||||
|
||||
new Chart(ctx, {
|
||||
type: chartType,
|
||||
data: {
|
||||
labels: chartData.labels,
|
||||
datasets: [{
|
||||
data: chartData.data,
|
||||
backgroundColor: colorPalette.slice(0, chartData.data.length),
|
||||
borderWidth: 2,
|
||||
borderColor: '#fff'
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
padding: 15,
|
||||
usePointStyle: true
|
||||
}
|
||||
}
|
||||
},
|
||||
...(chartType === 'bar' ? {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
stepSize: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
} : {})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 데이터 내보내기 함수들
|
||||
function exportToExcel(surveyId) {
|
||||
window.location.href = `export.php?sv_id=${surveyId}&format=excel`;
|
||||
}
|
||||
|
||||
function exportToCSV(surveyId) {
|
||||
window.location.href = `export.php?sv_id=${surveyId}&format=csv`;
|
||||
}
|
||||
|
||||
// 유틸리티 함수들
|
||||
const StatisticsUtils = {
|
||||
formatNumber: function(num) {
|
||||
return new Intl.NumberFormat('ko-KR').format(num);
|
||||
},
|
||||
|
||||
formatPercentage: function(num) {
|
||||
return num.toFixed(1) + '%';
|
||||
},
|
||||
|
||||
calculatePercentage: function(value, total) {
|
||||
return total > 0 ? (value / total) * 100 : 0;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user