diff --git a/css/styles.css b/css/styles.css index 885b229..d725f77 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1334,3 +1334,566 @@ footer { padding-bottom: 0; /* Remove padding since footer is no longer fixed */ } } + +/* ===== GAMIFICATION STYLES ===== */ + +/* Gamification Header */ +.gamification-header { + background: linear-gradient(135deg, var(--primary-color), #34495e); + color: white; + padding: 1.5rem; + border-radius: 15px; + margin: 2rem 0; + box-shadow: 0 8px 20px rgba(0,0,0,0.1); +} + +.gamification-stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); + gap: 1rem; + margin-top: 1rem; +} + +.stat-card { + background: rgba(255,255,255,0.1); + padding: 1rem; + border-radius: 10px; + text-align: center; + backdrop-filter: blur(10px); +} + +.stat-value { + font-size: 2rem; + font-weight: bold; + display: block; + margin-bottom: 0.5rem; +} + +.stat-label { + font-size: 0.9rem; + opacity: 0.9; +} + +.level-progress { + margin: 1rem 0; +} + +.level-info { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.5rem; +} + +.level-number { + font-size: 1.5rem; + font-weight: bold; +} + +.xp-info { + font-size: 0.9rem; + opacity: 0.9; +} + +.xp-progress-bar { + height: 8px; + background: rgba(255,255,255,0.2); + border-radius: 4px; + overflow: hidden; +} + +.xp-progress-fill { + height: 100%; + background: linear-gradient(90deg, #2ecc71, #27ae60); + transition: width 0.5s ease; +} + +/* Streak Display */ +.streak-display { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 1.1rem; +} + +.streak-flame { + animation: flicker 2s infinite alternate; +} + +@keyframes flicker { + 0% { opacity: 1; } + 50% { opacity: 0.8; } + 100% { opacity: 1; } +} + +/* Achievement Badges */ +.achievement-section { + margin: 2rem 0; +} + +.achievement-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.achievement-stats { + font-size: 1.1rem; + color: var(--accent-color); + font-weight: 500; +} + +.achievement-categories { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; + flex-wrap: wrap; +} + +.category-tab { + padding: 0.5rem 1rem; + border: 2px solid #ddd; + background: white; + border-radius: 20px; + cursor: pointer; + transition: all 0.3s ease; + font-size: 0.9rem; +} + +.category-tab.active { + background: var(--accent-color); + color: white; + border-color: var(--accent-color); +} + +.category-tab:hover { + border-color: var(--accent-color); +} + +.achievement-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 1rem; +} + +.achievement-badge { + background: white; + border-radius: 10px; + padding: 1rem; + box-shadow: 0 4px 8px rgba(0,0,0,0.1); + transition: transform 0.3s ease; + display: flex; + align-items: center; + gap: 1rem; +} + +.achievement-badge:hover { + transform: translateY(-2px); + box-shadow: 0 6px 12px rgba(0,0,0,0.15); +} + +.achievement-badge.earned { + border-left: 4px solid #2ecc71; +} + +.achievement-badge.locked { + opacity: 0.6; + border-left: 4px solid #bdc3c7; +} + +.badge-icon { + font-size: 2.5rem; + width: 60px; + height: 60px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + border: 3px solid #2ecc71; + background: rgba(46, 204, 113, 0.1); +} + +.badge-info { + flex: 1; +} + +.badge-name { + margin: 0 0 0.5rem 0; + font-size: 1.1rem; + font-weight: 600; + color: var(--text-color); +} + +.badge-description { + margin: 0 0 0.5rem 0; + color: #666; + font-size: 0.9rem; +} + +.badge-category { + font-size: 0.8rem; + font-weight: 500; + text-transform: uppercase; +} + +.badge-progress { + margin-top: 0.5rem; +} + +.badge-progress .progress-bar { + height: 4px; + background: #f0f0f0; + border-radius: 2px; + margin-bottom: 0.25rem; +} + +.badge-progress .progress-fill { + height: 100%; + background: #3498db; + border-radius: 2px; + transition: width 0.5s ease; +} + +.badge-progress .progress-text { + font-size: 0.8rem; + color: #666; +} + +/* Challenges Section */ +.challenges-section { + margin: 2rem 0; +} + +.challenges-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.challenges-progress { + font-size: 1.1rem; + color: var(--accent-color); + font-weight: 500; +} + +.challenges-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); + gap: 1rem; +} + +.challenge-card { + background: white; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 4px 8px rgba(0,0,0,0.1); + transition: all 0.3s ease; + border-left: 4px solid #3498db; +} + +.challenge-card:hover { + transform: translateY(-2px); + box-shadow: 0 6px 15px rgba(0,0,0,0.15); +} + +.challenge-card.completed { + border-left-color: #2ecc71; + background: linear-gradient(135deg, #f8fff9, #e8f8f0); +} + +.challenge-header { + display: flex; + align-items: flex-start; + gap: 1rem; + margin-bottom: 1rem; +} + +.challenge-icon { + font-size: 2rem; + width: 50px; + height: 50px; + border-radius: 50%; + background: rgba(52, 152, 219, 0.1); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.challenge-info { + flex: 1; +} + +.challenge-name { + margin: 0 0 0.5rem 0; + font-size: 1.2rem; + font-weight: 600; + color: var(--text-color); +} + +.challenge-description { + margin: 0; + color: #666; + font-size: 0.9rem; + line-height: 1.4; +} + +.challenge-meta { + display: flex; + flex-direction: column; + gap: 0.5rem; + align-items: flex-end; +} + +.challenge-type { + padding: 0.25rem 0.75rem; + border-radius: 12px; + font-size: 0.8rem; + font-weight: 500; + color: white; + text-transform: uppercase; +} + +.challenge-xp { + font-size: 0.9rem; + font-weight: 600; + color: #f39c12; +} + +.challenge-progress { + margin-top: 1rem; +} + +.challenge-progress .progress-bar { + height: 8px; + background: #f0f0f0; + border-radius: 4px; + margin-bottom: 0.5rem; + overflow: hidden; +} + +.challenge-progress .progress-fill { + height: 100%; + background: linear-gradient(90deg, #3498db, #2980b9); + border-radius: 4px; + transition: width 0.5s ease; +} + +.challenge-progress .progress-text { + font-size: 0.9rem; + color: #666; + font-weight: 500; +} + +.challenge-completed { + text-align: center; + margin-top: 1rem; + padding: 0.5rem; + background: rgba(46, 204, 113, 0.1); + border-radius: 6px; + color: #2ecc71; + font-weight: 600; +} + +.no-challenges { + text-align: center; + padding: 2rem; + color: #666; + font-style: italic; +} + +/* Notifications */ +.gamification-notification { + position: fixed; + top: 20px; + right: 20px; + background: white; + border-radius: 8px; + padding: 1rem 1.5rem; + box-shadow: 0 4px 12px rgba(0,0,0,0.15); + z-index: 10000; + max-width: 400px; + animation: slideInRight 0.3s ease; + border-left: 4px solid #3498db; +} + +.gamification-notification.success { + border-left-color: #2ecc71; +} + +.gamification-notification.achievement { + border-left-color: #f39c12; + background: linear-gradient(135deg, #fff9f0, #fef5e7); +} + +.notification-content { + display: flex; + justify-content: space-between; + align-items: center; +} + +.notification-message { + flex: 1; + font-size: 0.95rem; + color: var(--text-color); +} + +.notification-close { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + color: #999; + margin-left: 1rem; +} + +.notification-close:hover { + color: #666; +} + +@keyframes slideInRight { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +/* Gamification Dashboard */ +.gamification-dashboard { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 2rem; + border-radius: 20px; + margin: 2rem 0; + box-shadow: 0 10px 25px rgba(0,0,0,0.2); +} + +.dashboard-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; + margin-top: 1.5rem; +} + +.dashboard-card { + background: rgba(255,255,255,0.1); + padding: 1.5rem; + border-radius: 15px; + backdrop-filter: blur(10px); + border: 1px solid rgba(255,255,255,0.2); +} + +.dashboard-card h4 { + margin: 0 0 1rem 0; + font-size: 1.1rem; + opacity: 0.9; +} + +.dashboard-stat { + font-size: 2.5rem; + font-weight: bold; + margin-bottom: 0.5rem; + display: block; +} + +/* Leaderboard */ +.leaderboard-section { + margin: 2rem 0; +} + +.leaderboard-card { + background: white; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 4px 8px rgba(0,0,0,0.1); +} + +.leaderboard-item { + display: flex; + align-items: center; + padding: 1rem; + border-radius: 8px; + margin-bottom: 0.5rem; + background: #f8f9fa; + transition: all 0.3s ease; +} + +.leaderboard-item:hover { + background: #e9ecef; + transform: translateX(5px); +} + +.leaderboard-rank { + font-size: 1.2rem; + font-weight: bold; + width: 40px; + text-align: center; + color: var(--accent-color); +} + +.leaderboard-info { + flex: 1; + margin-left: 1rem; +} + +.leaderboard-name { + font-weight: 600; + margin-bottom: 0.25rem; +} + +.leaderboard-details { + font-size: 0.9rem; + color: #666; +} + +.leaderboard-score { + font-size: 1.1rem; + font-weight: bold; + color: var(--accent-color); +} + +/* Responsive Design for Gamification */ +@media (max-width: 768px) { + .gamification-stats { + grid-template-columns: repeat(2, 1fr); + gap: 0.75rem; + } + + .achievement-grid { + grid-template-columns: 1fr; + } + + .challenges-grid { + grid-template-columns: 1fr; + } + + .dashboard-grid { + grid-template-columns: 1fr; + gap: 1rem; + } + + .challenge-header { + flex-direction: column; + align-items: flex-start; + gap: 0.75rem; + } + + .challenge-meta { + flex-direction: row; + align-items: center; + gap: 1rem; + } + + .gamification-notification { + top: 10px; + right: 10px; + left: 10px; + max-width: none; + } +} diff --git a/day.html b/day.html index 268ca9f..adb25fc 100644 --- a/day.html +++ b/day.html @@ -162,6 +162,28 @@

completedDays[`${day}_${lang}`] = true; localStorage.setItem('completedDays', JSON.stringify(completedDays)); + // Award XP for lesson completion + if (typeof window.gamificationSystem !== 'undefined') { + const perfect = false; // TODO: Add logic to detect perfect completion + const xpResult = window.gamificationSystem.completeLesson(day, lang, perfect); + + if (xpResult) { + // Show XP notification + setTimeout(() => { + window.gamificationSystem.showNotification( + `🎉 +${xpResult.xpAwarded} XP earned!`, + 'success' + ); + }, 500); + } + } + + // Update challenge progress + if (typeof window.challengeSystem !== 'undefined') { + window.challengeSystem.updateProgress('lesson_complete', 1); + window.challengeSystem.updateProgress('study_time', 5); // Assume 5 minutes per lesson + } + // Update button state completeBtn.classList.add('completed'); completeBtn.innerHTML = ' Completed'; @@ -448,5 +470,8 @@

}); + + + diff --git a/index.html b/index.html index 436c402..c02c9d3 100644 --- a/index.html +++ b/index.html @@ -37,6 +37,43 @@

Mandarin Pathways

开启您的中文学习之旅Your Journey to Chinese Language Mastery

+ +
+
+
+
+ Level 1 + 0 / 100 XP +
+
+
+
+
+ +
+
+ 0 + 总经验Total XP +
+
+
+ 🔥 + 0 +
+ 连击Day Streak +
+
+ 0 + 徽章Badges +
+
+ 0 + 本周经验Weekly XP +
+
+
+
+

掌握中文Master Mandarin Chinese

@@ -185,6 +222,18 @@

每日课程Daily Lessons
+ +
+ + +
+ + +
+ + +
+

核心语言技能Core Language Skills

@@ -360,10 +409,113 @@

书写系统 { + if (typeof window.challengeSystem !== 'undefined') { + renderChallenges(); + } + if (typeof window.achievementSystem !== 'undefined') { + renderAchievements(); + } + }, 100); + } + } + + // Update gamification dashboard display + function updateGamificationDisplay() { + if (typeof window.gamificationSystem === 'undefined') return; + + const userData = window.gamificationSystem.getUserData(); + + // Update level and XP + document.getElementById('user-level').textContent = userData.level; + document.getElementById('current-xp').textContent = userData.xp; + document.getElementById('total-xp').textContent = userData.xp; + + // Update XP to next level + const xpForNext = window.gamificationSystem.getXPForNextLevel(); + if (xpForNext !== null) { + document.getElementById('next-level-xp').textContent = userData.xp + xpForNext; + const progress = window.gamificationSystem.getProgressToNextLevel(); + document.getElementById('xp-progress-fill').style.width = progress + '%'; + } else { + document.getElementById('next-level-xp').textContent = 'MAX'; + document.getElementById('xp-progress-fill').style.width = '100%'; + } + + // Update streak + document.getElementById('current-streak').textContent = userData.currentStreak; + + // Update badges count + document.getElementById('badges-earned').textContent = userData.badges.length; + + // Update weekly XP + document.getElementById('weekly-xp').textContent = userData.weeklyXP; + } + + // Render challenges section + function renderChallenges() { + if (typeof window.challengeSystem === 'undefined') return; + + const container = document.getElementById('challenges-container'); + if (container) { + container.innerHTML = window.challengeSystem.renderChallengesSection(); + } + } + + // Render achievements section + function renderAchievements() { + if (typeof window.achievementSystem === 'undefined' || typeof window.gamificationSystem === 'undefined') return; + + const container = document.getElementById('achievements-container'); + const userData = window.gamificationSystem.getUserData(); + + if (container) { + container.innerHTML = ` +
+ ${window.achievementSystem.renderCategoryTabs()} + ${window.achievementSystem.renderBadgeGrid(userData, true)} +
+ `; + + // Add category tab functionality + const categoryTabs = container.querySelectorAll('.category-tab'); + categoryTabs.forEach(tab => { + tab.addEventListener('click', function() { + categoryTabs.forEach(t => t.classList.remove('active')); + this.classList.add('active'); + + const category = this.dataset.category; + const achievementGrid = container.querySelector('.achievement-grid'); + + if (category === 'all') { + achievementGrid.innerHTML = window.achievementSystem.renderBadgeGrid(userData, true).split('achievement-grid">')[1].split('

')[0]; + } else { + const filteredHTML = window.achievementSystem.renderBadgeGrid(userData, true, category); + achievementGrid.innerHTML = filteredHTML.split('achievement-grid">')[1].split('')[0]; + } + }); + }); + } + } + function updateLanguageProgress(lang, completed, completedDays) { // Find the language card const cards = document.querySelectorAll('.language-card'); @@ -401,6 +553,9 @@

书写系统 + + +