document.addEventListener('DOMContentLoaded', () => { let gamificationData = AppState.getGamificationData(); // UI Elements const streakCount = document.getElementById('streakCount'); const streakIcon = document.getElementById('streakIcon'); const streakMessage = document.getElementById('streakMessage'); const progressFill = document.getElementById('progressFill'); const daysCompleted = document.getElementById('daysCompleted'); const weekGrid = document.getElementById('weekGrid'); const achievementsGrid = document.getElementById('achievementsGrid'); const habitToggle = document.getElementById('habitToggle'); const toast = document.getElementById('toast'); const toastIcon = document.getElementById('toastIcon'); const toastText = document.getElementById('toastText'); const confettiContainer = document.getElementById('confettiContainer'); const motivationalMessages = [ "불을 이어가세요!", "오늘 불이 나고 있어요!", "놀라운 일관성!", "아무도 당신을 막을 수 없어요!", "챔피언의 행동!" ]; const dailyTips = [ { text: "작은 걸음이 큰 변화를 만듭니다! 오늘 5분만 투자하세요.", author: "일일 동기" }, { text: "정돈된 공간은 정돈된 마음을 만듭니다. 작게 시작하세요!", author: "정리의 지혜" }, { text: "정리된 모든 파일이 진보입니다.庆祝하세요!", author: "업적 달성" }, { text: "미래의 당신이 오늘 정리한 것에 감사할 것입니다.", author: "타임 트래블러" }, { text: "일관성이 완벽함을 이깁니다. 매일来吧!", author: "습관 마스터" } ]; // Animate streak count function animateCount(element, target, duration = 1500) { const start = 0; const startTime = performance.now(); function update(currentTime) { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); const easeOut = 1 - Math.pow(1 - progress, 3); const current = Math.floor(start + (target - start) * easeOut); element.textContent = current; if (progress < 1) { requestAnimationFrame(update); } } requestAnimationFrame(update); } // Render week grid function renderWeekGrid(progress) { const days = ['M', 'T', 'W', 'T', 'F', 'S', 'S']; const today = new Date().getDay(); const mondayIndex = today === 0 ? 6 : today - 1; weekGrid.innerHTML = days.map((day, i) => { const completed = progress[i]; const isToday = i === mondayIndex; return `
${day}
${completed ? '✅' : (isToday ? '◉' : '')}
`; }).join(''); } // Render achievements function renderAchievements(achievements) { achievementsGrid.innerHTML = achievements.map(ach => `
${ach.icon} ${ach.name}
${ach.requirement}
`).join(''); } // Show toast notification function showToast(icon, message) { toastIcon.textContent = icon; toastText.textContent = message; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 3000); } // Confetti celebration function triggerConfetti() { const colors = ['#6366f1', '#f472b6', '#34d399', '#fbbf24', '#818cf8', '#34d399']; const confettiCount = 50; for (let i = 0; i < confettiCount; i++) { const confetti = document.createElement('div'); confetti.className = 'confetti'; confetti.style.left = Math.random() * 100 + 'vw'; confetti.style.background = colors[Math.floor(Math.random() * colors.length)]; confetti.style.borderRadius = Math.random() > 0.5 ? '50%' : '0'; confetti.style.width = Math.random() * 10 + 5 + 'px'; confetti.style.height = confetti.style.width; confetti.style.animation = `confettiFall ${Math.random() * 2 + 2}s ease-out forwards`; confetti.style.animationDelay = Math.random() * 0.5 + 's'; confettiContainer.appendChild(confetti); setTimeout(() => { confetti.remove(); }, 4000); } } // Trigger badge unlock animation function animateBadgeUnlock(achievementId) { const badge = document.querySelector(`.achievement[data-id="${achievementId}"]`); if (badge) { badge.classList.add('just-unlocked'); // Add sparkles for (let i = 0; i < 6; i++) { const sparkle = document.createElement('span'); sparkle.className = 'sparkle'; sparkle.textContent = '✨'; sparkle.style.left = Math.random() * 100 + '%'; sparkle.style.top = Math.random() * 100 + '%'; badge.appendChild(sparkle); } setTimeout(() => { badge.classList.remove('just-unlocked'); badge.querySelectorAll('.sparkle').forEach(s => s.remove()); }, 600); } } // Initialize page function init() { gamificationData = AppState.getGamificationData(); // Animate streak count animateCount(streakCount, gamificationData.streak); // Streak icon animation if (gamificationData.streak > 0) { streakIcon.classList.add('animate'); setTimeout(() => streakIcon.classList.remove('animate'), 1000); } // Update streak message if (gamificationData.streak > 0) { streakMessage.textContent = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)]; } // Animate progress bar const completedDays = gamificationData.weeklyProgress.filter(Boolean).length; setTimeout(() => { progressFill.style.width = (completedDays / 7 * 100) + '%'; }, 300); daysCompleted.textContent = completedDays; // Render week grid renderWeekGrid(gamificationData.weeklyProgress); // Render achievements renderAchievements(gamificationData.achievements); // Set habit toggle state habitToggle.checked = gamificationData.habitReminderEnabled; // Random daily tip const randomTip = dailyTips[Math.floor(Math.random() * dailyTips.length)]; document.getElementById('tipText').textContent = `"${randomTip.text}"`; document.querySelector('.tip-author').textContent = `— ${randomTip.author}`; // Habit toggle handler habitToggle.addEventListener('change', (e) => { gamificationData.habitReminderEnabled = e.target.checked; AppState.setGamificationData(gamificationData); showToast(e.target.checked ? '🔔' : '🔕', e.target.checked ? 'Reminders enabled!' : 'Reminders disabled'); }); // Achievement click handler (for demo unlock) achievementsGrid.addEventListener('click', (e) => { const achievement = e.target.closest('.achievement'); if (achievement && !achievement.classList.contains('unlocked')) { // Simulate unlock for demo const achId = achievement.dataset.id; const achData = gamificationData.achievements.find(a => a.id === achId); if (achData) { achData.unlocked = true; AppState.setGamificationData(gamificationData); animateBadgeUnlock(achId); triggerConfetti(); showToast(achData.icon, `${achData.name} unlocked!`); renderAchievements(gamificationData.achievements); } } }); } // Run on load init(); });