first commit 2

This commit is contained in:
hmw1001
2026-06-11 18:47:38 +09:00
parent c768729ce6
commit 6f534e33a6
11095 changed files with 1595758 additions and 0 deletions
+296
View File
@@ -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;
}
};