Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>STEM Quest - Full Stack Learning Platform</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| /* Custom animations */ | |
| @keyframes pulse { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.05); } | |
| 100% { transform: scale(1); } | |
| } | |
| @keyframes shake { | |
| 0%, 100% { transform: translateX(0); } | |
| 25% { transform: translateX(-5px); } | |
| 75% { transform: translateX(5px); } | |
| } | |
| .pulse-animation { | |
| animation: pulse 1.5s infinite; | |
| } | |
| .shake-animation { | |
| animation: shake 0.5s; | |
| } | |
| .subject-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 20px rgba(0,0,0,0.1); | |
| } | |
| .flip-card { | |
| perspective: 1000px; | |
| } | |
| .flip-card-inner { | |
| transition: transform 0.6s; | |
| transform-style: preserve-3d; | |
| } | |
| .flip-card.flipped .flip-card-inner { | |
| transform: rotateY(180deg); | |
| } | |
| .flip-card-front, .flip-card-back { | |
| backface-visibility: hidden; | |
| } | |
| .flip-card-back { | |
| transform: rotateY(180deg); | |
| } | |
| /* Custom colors for subjects */ | |
| .math-bg { background-color: #6366f1; } | |
| .physics-bg { background-color: #3b82f6; } | |
| .chemistry-bg { background-color: #10b981; } | |
| .biology-bg { background-color: #84cc16; } | |
| .science-bg { background-color: #f59e0b; } | |
| .math-text { color: #6366f1; } | |
| .physics-text { color: #3b82f6; } | |
| .chemistry-text { color: #10b981; } | |
| .biology-text { color: #84cc16; } | |
| .science-text { color: #f59e0b; } | |
| .math-border { border-color: #6366f1; } | |
| .physics-border { border-color: #3b82f6; } | |
| .chemistry-border { border-color: #10b981; } | |
| .biology-border { border-color: #84cc16; } | |
| .science-border { border-color: #f59e0b; } | |
| /* Loading spinner */ | |
| .spinner { | |
| width: 40px; | |
| height: 40px; | |
| border: 4px solid rgba(0, 0, 0, 0.1); | |
| border-left-color: #6366f1; | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <!-- Navigation --> | |
| <nav class="bg-white shadow-lg"> | |
| <div class="max-w-6xl mx-auto px-4"> | |
| <div class="flex justify-between"> | |
| <div class="flex space-x-7"> | |
| <div> | |
| <a href="#" class="flex items-center py-4 px-2"> | |
| <i class="fas fa-atom text-indigo-600 text-2xl mr-2"></i> | |
| <span class="font-semibold text-gray-900 text-lg">STEM Quest</span> | |
| </a> | |
| </div> | |
| </div> | |
| <div class="hidden md:flex items-center space-x-3"> | |
| <a href="#" class="py-2 px-2 font-medium text-gray-500 border-b-4 border-indigo-600 text-indigo-600 transition duration-300">Home</a> | |
| <a href="#courses" class="py-2 px-2 font-medium text-gray-500 border-b-4 border-transparent hover:text-indigo-600 transition duration-300">Courses</a> | |
| <a href="#leaderboard" class="py-2 px-2 font-medium text-gray-500 border-b-4 border-transparent hover:text-indigo-600 transition duration-300">Leaderboard</a> | |
| <a href="#profile" class="py-2 px-2 font-medium text-gray-500 border-b-4 border-transparent hover:text-indigo-600 transition duration-300">Profile</a> | |
| </div> | |
| <div class="md:hidden flex items-center"> | |
| <button class="outline-none mobile-menu-button"> | |
| <i class="fas fa-bars text-gray-500 text-xl"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="hidden mobile-menu"> | |
| <ul class=""> | |
| <li class="active"><a href="#" class="block text-sm px-2 py-4 hover:bg-indigo-500 transition duration-300">Home</a></li> | |
| <li><a href="#courses" class="block text-sm px-2 py-4 hover:bg-indigo-500 transition duration-300">Courses</a></li> | |
| <li><a href="#leaderboard" class="block text-sm px-2 py-4 hover:bg-indigo-500 transition duration-300">Leaderboard</a></li> | |
| <li><a href="#profile" class="block text-sm px-2 py-4 hover:bg-indigo-500 transition duration-300">Profile</a></li> | |
| </ul> | |
| </div> | |
| </nav> | |
| <!-- Hero Section --> | |
| <div class="bg-indigo-600 text-white py-16"> | |
| <div class="container mx-auto px-6 text-center"> | |
| <h1 class="text-4xl md:text-5xl font-bold mb-6">Master STEM with Fun!</h1> | |
| <p class="text-xl mb-8">Learn Math, Physics, Chemistry, Biology and Science through interactive lessons and gamified challenges.</p> | |
| <button id="startLearningBtn" class="bg-white text-indigo-600 font-bold rounded-full py-3 px-8 shadow-lg hover:bg-gray-100 transition duration-300"> | |
| Start Learning Now | |
| </button> | |
| </div> | |
| </div> | |
| <!-- User Stats --> | |
| <div class="container mx-auto px-6 py-8"> | |
| <div class="bg-white rounded-xl shadow-md p-6 mb-8"> | |
| <div class="flex flex-col md:flex-row items-center justify-between"> | |
| <div class="flex items-center mb-4 md:mb-0"> | |
| <div class="w-16 h-16 rounded-full bg-indigo-100 flex items-center justify-center mr-4"> | |
| <i class="fas fa-user-graduate text-indigo-600 text-2xl"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-bold text-lg">Welcome back, <span id="usernameDisplay">Explorer</span>!</h3> | |
| <p class="text-gray-600">Keep your streak going!</p> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4 w-full md:w-auto"> | |
| <div class="bg-indigo-50 rounded-lg p-3 text-center"> | |
| <div class="text-indigo-600 font-bold text-xl" id="streakCount">5</div> | |
| <div class="text-gray-600 text-sm">Day Streak</div> | |
| </div> | |
| <div class="bg-green-50 rounded-lg p-3 text-center"> | |
| <div class="text-green-600 font-bold text-xl" id="xpCount">1,250</div> | |
| <div class="text-gray-600 text-sm">XP Points</div> | |
| </div> | |
| <div class="bg-yellow-50 rounded-lg p-3 text-center"> | |
| <div class="text-yellow-600 font-bold text-xl" id="badgeCount">8</div> | |
| <div class="text-gray-600 text-sm">Badges</div> | |
| </div> | |
| <div class="bg-purple-50 rounded-lg p-3 text-center"> | |
| <div class="text-purple-600 font-bold text-xl" id="lessonCount">15</div> | |
| <div class="text-gray-600 text-sm">Lessons</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Progress Bar --> | |
| <div class="mt-6"> | |
| <div class="flex justify-between mb-1"> | |
| <span class="text-sm font-medium">Level <span id="currentLevel">5</span> Progress</span> | |
| <span class="text-sm font-medium"><span id="progressPercent">65</span>%</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> | |
| <div class="bg-indigo-600 h-2.5 rounded-full" id="levelProgressBar" style="width: 65%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Subjects Grid --> | |
| <div class="container mx-auto px-6 py-8" id="courses"> | |
| <h2 class="text-2xl font-bold mb-6">Choose Your Subject</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" id="subjectsContainer"> | |
| <!-- Subjects will be loaded here dynamically --> | |
| <div class="text-center py-8"> | |
| <div class="spinner mx-auto"></div> | |
| <p class="mt-4 text-gray-600">Loading subjects...</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Daily Challenge --> | |
| <div class="container mx-auto px-6 py-8"> | |
| <div class="bg-gradient-to-r from-indigo-500 to-blue-600 rounded-xl shadow-lg p-6 text-white"> | |
| <div class="flex flex-col md:flex-row items-center justify-between"> | |
| <div class="mb-4 md:mb-0"> | |
| <h2 class="text-2xl font-bold mb-2">Daily Challenge</h2> | |
| <p class="mb-4">Complete today's challenge to earn bonus XP and keep your streak alive!</p> | |
| <div class="flex items-center"> | |
| <div class="bg-white bg-opacity-20 rounded-full p-2 mr-3"> | |
| <i class="fas fa-bolt text-yellow-300"></i> | |
| </div> | |
| <span>+50 XP</span> | |
| </div> | |
| </div> | |
| <div class="bg-white bg-opacity-20 rounded-lg p-4 w-full md:w-auto"> | |
| <h3 class="font-bold mb-2" id="challengeQuestion">Solve this equation:</h3> | |
| <p class="text-xl mb-4" id="challengeText">2x + 5 = 15</p> | |
| <div class="flex"> | |
| <input type="text" id="challengeAnswer" class="rounded-l-lg px-4 py-2 w-full text-gray-900" placeholder="Your answer"> | |
| <button id="submitChallengeBtn" class="bg-yellow-400 text-indigo-800 font-bold px-4 py-2 rounded-r-lg hover:bg-yellow-300 transition duration-300"> | |
| Submit | |
| </button> | |
| </div> | |
| <p class="text-sm mt-2 hidden" id="challengeFeedback"></p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Leaderboard --> | |
| <div class="container mx-auto px-6 py-8" id="leaderboard"> | |
| <h2 class="text-2xl font-bold mb-6">Top Learners This Week</h2> | |
| <div class="bg-white rounded-xl shadow-md overflow-hidden"> | |
| <div class="overflow-x-auto"> | |
| <table class="w-full"> | |
| <thead class="bg-gray-50"> | |
| <tr> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Rank</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">User</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">XP</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Level</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Streak</th> | |
| </tr> | |
| </thead> | |
| <tbody class="bg-white divide-y divide-gray-200" id="leaderboardBody"> | |
| <!-- Leaderboard data will be loaded here --> | |
| <tr> | |
| <td colspan="5" class="px-6 py-4 text-center"> | |
| <div class="spinner mx-auto"></div> | |
| <p class="mt-2 text-gray-600">Loading leaderboard...</p> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Quiz Example --> | |
| <div class="container mx-auto px-6 py-8"> | |
| <h2 class="text-2xl font-bold mb-6">Try a Sample Quiz</h2> | |
| <div class="bg-white rounded-xl shadow-lg overflow-hidden"> | |
| <div class="p-6"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <div> | |
| <span class="inline-block px-3 py-1 text-sm font-semibold math-bg text-white rounded-full mb-2">Mathematics</span> | |
| <h3 class="text-xl font-bold">Algebra Basics</h3> | |
| </div> | |
| <div class="flex items-center"> | |
| <div class="flex mr-4" id="quizLives"> | |
| <i class="fas fa-heart text-red-500 mx-1"></i> | |
| <i class="fas fa-heart text-red-500 mx-1"></i> | |
| <i class="fas fa-heart text-red-500 mx-1"></i> | |
| </div> | |
| <div class="bg-gray-100 px-3 py-1 rounded-full"> | |
| <span class="font-bold">5</span> XP | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Question --> | |
| <div class="mb-8"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center mr-3"> | |
| <span class="text-indigo-600 font-bold">1</span> | |
| </div> | |
| <h4 class="font-medium">Solve for x: 3x - 7 = 14</h4> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-3 ml-11"> | |
| <button class="quiz-option border-2 border-gray-200 rounded-lg px-4 py-3 text-left hover:border-indigo-400 transition duration-300" data-correct="false"> | |
| <span class="font-bold mr-2">A)</span> x = 5 | |
| </button> | |
| <button class="quiz-option border-2 border-gray-200 rounded-lg px-4 py-3 text-left hover:border-indigo-400 transition duration-300" data-correct="true"> | |
| <span class="font-bold mr-2">B)</span> x = 7 | |
| </button> | |
| <button class="quiz-option border-2 border-gray-200 rounded-lg px-4 py-3 text-left hover:border-indigo-400 transition duration-300" data-correct="false"> | |
| <span class="font-bold mr-2">C)</span> x = 9 | |
| </button> | |
| <button class="quiz-option border-2 border-gray-200 rounded-lg px-4 py-3 text-left hover:border-indigo-400 transition duration-300" data-correct="false"> | |
| <span class="font-bold mr-2">D)</span> x = 11 | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Explanation (hidden initially) --> | |
| <div class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6 hidden" id="explanation"> | |
| <div class="flex"> | |
| <div class="flex-shrink-0"> | |
| <i class="fas fa-info-circle text-blue-500"></i> | |
| </div> | |
| <div class="ml-3"> | |
| <h3 class="text-sm font-medium text-blue-800">Explanation</h3> | |
| <div class="mt-2 text-sm text-blue-700"> | |
| <p>To solve 3x - 7 = 14:</p> | |
| <ol class="list-decimal pl-5 mt-1 space-y-1"> | |
| <li>Add 7 to both sides: 3x = 21</li> | |
| <li>Divide both sides by 3: x = 7</li> | |
| </ol> | |
| <p class="mt-2">The correct answer is B) x = 7</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Navigation --> | |
| <div class="flex justify-between"> | |
| <button class="bg-gray-200 text-gray-700 px-6 py-2 rounded-lg hover:bg-gray-300 transition duration-300"> | |
| <i class="fas fa-arrow-left mr-2"></i> Back | |
| </button> | |
| <button class="bg-indigo-600 text-white px-6 py-2 rounded-lg hover:bg-indigo-700 transition duration-300"> | |
| Next <i class="fas fa-arrow-right ml-2"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Badges Collection --> | |
| <div class="container mx-auto px-6 py-8" id="profile"> | |
| <h2 class="text-2xl font-bold mb-6">Your Badges</h2> | |
| <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4" id="badgesContainer"> | |
| <!-- Badges will be loaded here dynamically --> | |
| <div class="text-center py-8 col-span-6"> | |
| <div class="spinner mx-auto"></div> | |
| <p class="mt-4 text-gray-600">Loading badges...</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Community Forum Preview --> | |
| <div class="container mx-auto px-6 py-8"> | |
| <h2 class="text-2xl font-bold mb-6">Community Discussions</h2> | |
| <div class="bg-white rounded-xl shadow-md overflow-hidden"> | |
| <div class="p-6"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h3 class="text-lg font-bold">Top Questions</h3> | |
| <button class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition duration-300"> | |
| Ask Question | |
| </button> | |
| </div> | |
| <div class="space-y-4" id="discussionsContainer"> | |
| <!-- Discussions will be loaded here dynamically --> | |
| <div class="text-center py-8"> | |
| <div class="spinner mx-auto"></div> | |
| <p class="mt-4 text-gray-600">Loading discussions...</p> | |
| </div> | |
| </div> | |
| <div class="mt-6 text-center"> | |
| <button class="text-indigo-600 font-medium hover:underline"> | |
| View All Discussions <i class="fas fa-arrow-right ml-1"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Footer --> | |
| <footer class="bg-gray-800 text-white pt-12 pb-6"> | |
| <div class="container mx-auto px-6"> | |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> | |
| <div> | |
| <h3 class="text-lg font-bold mb-4">STEM Quest</h3> | |
| <p class="text-gray-400">Making STEM learning fun and engaging through gamification and interactive lessons.</p> | |
| <div class="flex mt-4 space-x-4"> | |
| <a href="#" class="text-gray-400 hover:text-white"> | |
| <i class="fab fa-facebook-f"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-white"> | |
| <i class="fab fa-twitter"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-white"> | |
| <i class="fab fa-instagram"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-white"> | |
| <i class="fab fa-youtube"></i> | |
| </a> | |
| </div> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-bold mb-4">Subjects</h3> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Mathematics</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Physics</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Chemistry</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Biology</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Science</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-bold mb-4">Resources</h3> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Blog</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Study Tips</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Practice Tests</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Video Lessons</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white">Community Forum</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-bold mb-4">Contact</h3> | |
| <ul class="space-y-2"> | |
| <li class="flex items-center text-gray-400"> | |
| <i class="fas fa-envelope mr-2"></i> support@stemquest.com | |
| </li> | |
| <li class="flex items-center text-gray-400"> | |
| <i class="fas fa-phone-alt mr-2"></i> (123) 456-7890 | |
| </li> | |
| <li class="flex items-start text-gray-400"> | |
| <i class="fas fa-map-marker-alt mr-2 mt-1"></i> | |
| <span>123 Learning St.<br>Edutown, ST 12345</span> | |
| </li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="border-t border-gray-700 mt-8 pt-6 flex flex-col md:flex-row justify-between items-center"> | |
| <p class="text-gray-400 text-sm">© 2023 STEM Quest. All rights reserved.</p> | |
| <div class="flex space-x-6 mt-4 md:mt-0"> | |
| <a href="#" class="text-gray-400 hover:text-white text-sm">Privacy Policy</a> | |
| <a href="#" class="text-gray-400 hover:text-white text-sm">Terms of Service</a> | |
| <a href="#" class="text-gray-400 hover:text-white text-sm">Cookie Policy</a> | |
| </div> | |
| </div> | |
| </div> | |
| </footer> | |
| <!-- Mock Database and API Simulation --> | |
| <script> | |
| // ============================================= | |
| // MOCK DATABASE - Simulating backend data | |
| // ============================================= | |
| const mockDatabase = { | |
| // Current user data | |
| currentUser: { | |
| id: 101, | |
| username: "STEMExplorer", | |
| avatar: "https://randomuser.me/api/portraits/women/44.jpg", | |
| streak: 5, | |
| xp: 1250, | |
| level: 5, | |
| levelProgress: 65, | |
| badges: [1, 2, 3, 4, 5, 6, 7, 8], // IDs of earned badges | |
| completedLessons: 15 | |
| }, | |
| // Subjects data | |
| subjects: [ | |
| { | |
| id: 1, | |
| name: "Mathematics", | |
| icon: "square-root-alt", | |
| description: "Master algebra, geometry, calculus and more through interactive problems.", | |
| rating: 4.5, | |
| colorClass: "math", | |
| lessons: 24, | |
| completed: 6 | |
| }, | |
| { | |
| id: 2, | |
| name: "Physics", | |
| icon: "atom", | |
| description: "Explore mechanics, electricity, waves and the fundamental laws of nature.", | |
| rating: 4, | |
| colorClass: "physics", | |
| lessons: 18, | |
| completed: 4 | |
| }, | |
| { | |
| id: 3, | |
| name: "Chemistry", | |
| icon: "flask", | |
| description: "Discover atoms, reactions, organic chemistry and the periodic table.", | |
| rating: 3.5, | |
| colorClass: "chemistry", | |
| lessons: 15, | |
| completed: 3 | |
| }, | |
| { | |
| id: 4, | |
| name: "Biology", | |
| icon: "dna", | |
| description: "Learn about cells, genetics, human anatomy and ecosystems.", | |
| rating: 4, | |
| colorClass: "biology", | |
| lessons: 12, | |
| completed: 2 | |
| }, | |
| { | |
| id: 5, | |
| name: "Science", | |
| icon: "globe-americas", | |
| description: "Explore earth science, astronomy, weather and basic experiments.", | |
| rating: 3, | |
| colorClass: "science", | |
| lessons: 10, | |
| completed: 0 | |
| } | |
| ], | |
| // Badges data | |
| badges: [ | |
| { | |
| id: 1, | |
| name: "Fast Learner", | |
| description: "Complete 5 lessons in one day", | |
| icon: "medal", | |
| color: "yellow", | |
| earned: true | |
| }, | |
| { | |
| id: 2, | |
| name: "7-Day Streak", | |
| description: "Learn for 7 consecutive days", | |
| icon: "fire", | |
| color: "indigo", | |
| earned: true | |
| }, | |
| { | |
| id: 3, | |
| name: "Quick Thinker", | |
| description: "Answer 3 questions in a row correctly", | |
| icon: "brain", | |
| color: "green", | |
| earned: true | |
| }, | |
| { | |
| id: 4, | |
| name: "Early Bird", | |
| description: "Complete a lesson before 7 AM", | |
| icon: "sun", | |
| color: "amber", | |
| earned: true | |
| }, | |
| { | |
| id: 5, | |
| name: "Weekend Warrior", | |
| description: "Complete lessons on both weekend days", | |
| icon: "calendar-week", | |
| color: "purple", | |
| earned: true | |
| }, | |
| { | |
| id: 6, | |
| name: "Subject Starter", | |
| description: "Begin learning in 3 different subjects", | |
| icon: "book-open", | |
| color: "blue", | |
| earned: true | |
| }, | |
| { | |
| id: 7, | |
| name: "Community Helper", | |
| description: "Answer 5 questions in the forum", | |
| icon: "hands-helping", | |
| color: "teal", | |
| earned: true | |
| }, | |
| { | |
| id: 8, | |
| name: "Challenge Champion", | |
| description: "Complete 5 daily challenges", | |
| icon: "trophy", | |
| color: "red", | |
| earned: true | |
| }, | |
| { | |
| id: 9, | |
| name: "Math Master", | |
| description: "Complete 10 math lessons", | |
| icon: "calculator", | |
| color: "indigo", | |
| earned: false | |
| }, | |
| { | |
| id: 10, | |
| name: "Perfect Score", | |
| description: "Complete a lesson with no mistakes", | |
| icon: "star", | |
| color: "yellow", | |
| earned: false | |
| }, | |
| { | |
| id: 11, | |
| name: "Night Owl", | |
| description: "Complete a lesson after 10 PM", | |
| icon: "moon", | |
| color: "gray", | |
| earned: false | |
| }, | |
| { | |
| id: 12, | |
| name: "Subject Expert", | |
| description: "Complete all lessons in one subject", | |
| icon: "award", | |
| color: "purple", | |
| earned: false | |
| } | |
| ], | |
| // Leaderboard data | |
| leaderboard: [ | |
| { | |
| id: 201, | |
| name: "Sarah Johnson", | |
| title: "Math Master", | |
| avatar: "https://randomuser.me/api/portraits/women/12.jpg", | |
| xp: 3450, | |
| level: 15, | |
| streak: 21 | |
| }, | |
| { | |
| id: 202, | |
| name: "Michael Chen", | |
| title: "Physics Pro", | |
| avatar: "https://randomuser.me/api/portraits/men/32.jpg", | |
| xp: 3120, | |
| level: 14, | |
| streak: 18 | |
| }, | |
| { | |
| id: 203, | |
| name: "Emma Rodriguez", | |
| title: "Chemistry Champ", | |
| avatar: "https://randomuser.me/api/portraits/women/45.jpg", | |
| xp: 2980, | |
| level: 13, | |
| streak: 15 | |
| }, | |
| { | |
| id: 204, | |
| name: "David Kim", | |
| title: "Biology Buff", | |
| avatar: "https://randomuser.me/api/portraits/men/22.jpg", | |
| xp: 2850, | |
| level: 13, | |
| streak: 12 | |
| }, | |
| { | |
| id: 205, | |
| name: "Lisa Wong", | |
| title: "Science Star", | |
| avatar: "https://randomuser.me/api/portraits/women/33.jpg", | |
| xp: 2760, | |
| level: 12, | |
| streak: 10 | |
| } | |
| ], | |
| // Discussions data | |
| discussions: [ | |
| { | |
| id: 301, | |
| userId: 201, | |
| userName: "Sarah Johnson", | |
| userAvatar: "https://randomuser.me/api/portraits/women/12.jpg", | |
| title: "How do I solve quadratic equations?", | |
| content: "I'm having trouble understanding the quadratic formula. Can someone explain it step by step?", | |
| time: "2 hours ago", | |
| replies: 5, | |
| likes: 8, | |
| subject: "math" | |
| }, | |
| { | |
| id: 302, | |
| userId: 203, | |
| userName: "Emma Rodriguez", | |
| userAvatar: "https://randomuser.me/api/portraits/women/45.jpg", | |
| title: "Best resources for learning organic chemistry?", | |
| content: "I'm struggling with reaction mechanisms. Any recommended study materials or techniques?", | |
| time: "5 hours ago", | |
| replies: 3, | |
| likes: 4, | |
| subject: "chemistry" | |
| }, | |
| { | |
| id: 303, | |
| userId: 202, | |
| userName: "Michael Chen", | |
| userAvatar: "https://randomuser.me/api/portraits/men/32.jpg", | |
| title: "Physics problem - calculating velocity", | |
| content: "If a car accelerates from 0 to 60 km/h in 5 seconds, what is its average acceleration?", | |
| time: "1 day ago", | |
| replies: 7, | |
| likes: 12, | |
| subject: "physics" | |
| } | |
| ], | |
| // Daily challenge | |
| dailyChallenge: { | |
| id: 401, | |
| question: "Solve this equation:", | |
| challenge: "2x + 5 = 15", | |
| answer: "5", | |
| xpReward: 50 | |
| } | |
| }; | |
| // ============================================= | |
| // API SIMULATION - Mock backend endpoints | |
| // ============================================= | |
| const mockAPI = { | |
| // Simulate API delay | |
| delay: () => new Promise(resolve => setTimeout(resolve, 800)), | |
| // Get current user data | |
| getCurrentUser: async () => { | |
| await mockAPI.delay(); | |
| return mockDatabase.currentUser; | |
| }, | |
| // Get all subjects | |
| getSubjects: async () => { | |
| await mockAPI.delay(); | |
| return mockDatabase.subjects; | |
| }, | |
| // Get leaderboard data | |
| getLeaderboard: async () => { | |
| await mockAPI.delay(); | |
| return mockDatabase.leaderboard; | |
| }, | |
| // Get user badges | |
| getBadges: async (userId) => { | |
| await mockAPI.delay(); | |
| return mockDatabase.badges; | |
| }, | |
| // Get community discussions | |
| getDiscussions: async () => { | |
| await mockAPI.delay(); | |
| return mockDatabase.discussions; | |
| }, | |
| // Get daily challenge | |
| getDailyChallenge: async () => { | |
| await mockAPI.delay(); | |
| return mockDatabase.dailyChallenge; | |
| }, | |
| // Submit daily challenge answer | |
| submitChallengeAnswer: async (userId, challengeId, answer) => { | |
| await mockAPI.delay(); | |
| const challenge = mockDatabase.dailyChallenge; | |
| const isCorrect = answer === challenge.answer; | |
| if (isCorrect) { | |
| // Update user stats | |
| mockDatabase.currentUser.xp += challenge.xpReward; | |
| mockDatabase.currentUser.streak += 1; | |
| // Check if level up | |
| if (mockDatabase.currentUser.xp >= mockDatabase.currentUser.level * 500) { | |
| mockDatabase.currentUser.level += 1; | |
| mockDatabase.currentUser.xp = 0; | |
| mockDatabase.currentUser.levelProgress = 0; | |
| } else { | |
| mockDatabase.currentUser.levelProgress = Math.floor((mockDatabase.currentUser.xp / (mockDatabase.currentUser.level * 500)) * 100); | |
| } | |
| } | |
| return { | |
| success: isCorrect, | |
| correctAnswer: challenge.answer, | |
| xpEarned: isCorrect ? challenge.xpReward : 0, | |
| streak: mockDatabase.currentUser.streak, | |
| userXp: mockDatabase.currentUser.xp, | |
| userLevel: mockDatabase.currentUser.level, | |
| userLevelProgress: mockDatabase.currentUser.levelProgress | |
| }; | |
| }, | |
| // Start a subject lesson | |
| startSubjectLesson: async (userId, subjectId) => { | |
| await mockAPI.delay(); | |
| return { | |
| success: true, | |
| lessonId: Math.floor(Math.random() * 1000) + 1000, | |
| subjectId: subjectId | |
| }; | |
| } | |
| }; | |
| // ============================================= | |
| // FRONTEND APPLICATION - UI and interaction | |
| // ============================================= | |
| document.addEventListener('DOMContentLoaded', async function() { | |
| // Mobile menu toggle | |
| const btn = document.querySelector('.mobile-menu-button'); | |
| const menu = document.querySelector('.mobile-menu'); | |
| btn.addEventListener('click', () => { | |
| menu.classList.toggle('hidden'); | |
| }); | |
| // Quiz interaction | |
| const quizOptions = document.querySelectorAll('.quiz-option'); | |
| const explanation = document.getElementById('explanation'); | |
| const quizLives = document.getElementById('quizLives'); | |
| quizOptions.forEach(option => { | |
| option.addEventListener('click', () => { | |
| // Remove any existing selection | |
| quizOptions.forEach(opt => { | |
| opt.classList.remove('border-indigo-600', 'bg-indigo-50'); | |
| opt.classList.add('border-gray-200'); | |
| }); | |
| // Select this option | |
| option.classList.remove('border-gray-200'); | |
| option.classList.add('border-indigo-600', 'bg-indigo-50'); | |
| // Show explanation | |
| explanation.classList.remove('hidden'); | |
| // Add shake animation to wrong options if needed | |
| if(option.dataset.correct === "false") { | |
| option.classList.add('shake-animation'); | |
| // Remove a life | |
| if (quizLives.children.length > 0) { | |
| quizLives.removeChild(quizLives.lastElementChild); | |
| } | |
| setTimeout(() => { | |
| option.classList.remove('shake-animation'); | |
| }, 500); | |
| } | |
| }); | |
| }); | |
| // Add pulse animation to daily challenge | |
| const dailyChallengeBtn = document.getElementById('submitChallengeBtn'); | |
| setInterval(() => { | |
| dailyChallengeBtn.classList.toggle('pulse-animation'); | |
| }, 3000); | |
| // ============================================= | |
| // DATA LOADING - Fetch and display data from mock API | |
| // ============================================= | |
| // Load current user data | |
| async function loadUserData() { | |
| try { | |
| const user = await mockAPI.getCurrentUser(); | |
| // Update UI with user data | |
| document.getElementById('usernameDisplay').textContent = user.username; | |
| document.getElementById('streakCount').textContent = user.streak; | |
| document.getElementById('xpCount').textContent = user.xp.toLocaleString(); | |
| document.getElementById('badgeCount').textContent = user.badges.length; | |
| document.getElementById('lessonCount').textContent = user.completedLessons; | |
| document.getElementById('currentLevel').textContent = user.level; | |
| document.getElementById('progressPercent').textContent = user.levelProgress; | |
| document.getElementById('levelProgressBar').style.width = `${user.levelProgress}%`; | |
| } catch (error) { | |
| console.error("Error loading user data:", error); | |
| } | |
| } | |
| // Load subjects | |
| async function loadSubjects() { | |
| try { | |
| const subjects = await mockAPI.getSubjects(); | |
| const container = document.getElementById('subjectsContainer'); | |
| // Clear loading state | |
| container.innerHTML = ''; | |
| // Add each subject card | |
| subjects.forEach(subject => { | |
| const stars = Math.floor(subject.rating); | |
| const hasHalfStar = subject.rating % 1 >= 0.5; | |
| let starsHTML = ''; | |
| for (let i = 0; i < stars; i++) { | |
| starsHTML += '<i class="fas fa-star text-yellow-400 mr-1"></i>'; | |
| } | |
| if (hasHalfStar) { | |
| starsHTML += '<i class="fas fa-star-half-alt text-yellow-400 mr-1"></i>'; | |
| } | |
| for (let i = stars + (hasHalfStar ? 1 : 0); i < 5; i++) { | |
| starsHTML += '<i class="far fa-star text-yellow-400 mr-1"></i>'; | |
| } | |
| const card = document.createElement('div'); | |
| card.className = `subject-card bg-white rounded-xl shadow-md overflow-hidden transition duration-300 transform hover:scale-105`; | |
| card.innerHTML = ` | |
| <div class="${subject.colorClass}-bg h-2"></div> | |
| <div class="p-6"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-12 h-12 rounded-full bg-${subject.colorClass}-100 flex items-center justify-center mr-4"> | |
| <i class="fas fa-${subject.icon} ${subject.colorClass}-text text-xl"></i> | |
| </div> | |
| <h3 class="font-bold text-lg ${subject.colorClass}-text">${subject.name}</h3> | |
| </div> | |
| <p class="text-gray-600 mb-4">${subject.description}</p> | |
| <div class="flex justify-between items-center"> | |
| <div class="flex"> | |
| ${starsHTML} | |
| </div> | |
| <button class="${subject.colorClass}-bg text-white px-4 py-2 rounded-lg hover:bg-${subject.colorClass}-700 transition duration-300 start-subject-btn" data-subject-id="${subject.id}"> | |
| Start | |
| </button> | |
| </div> | |
| <div class="mt-3 text-sm text-gray-500"> | |
| <div class="flex justify-between mb-1"> | |
| <span>Progress</span> | |
| <span>${subject.completed}/${subject.lessons} lessons</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-1.5"> | |
| <div class="${subject.colorClass}-bg h-1.5 rounded-full" style="width: ${(subject.completed / subject.lessons) * 100}%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| container.appendChild(card); | |
| }); | |
| // Add practice card | |
| const practiceCard = document.createElement('div'); | |
| practiceCard.className = 'subject-card bg-white rounded-xl shadow-md overflow-hidden transition duration-300 transform hover:scale-105'; | |
| practiceCard.innerHTML = ` | |
| <div class="bg-gradient-to-r from-purple-500 to-pink-500 h-2"></div> | |
| <div class="p-6"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center mr-4"> | |
| <i class="fas fa-brain text-purple-600 text-xl"></i> | |
| </div> | |
| <h3 class="font-bold text-lg text-purple-600">Practice Mode</h3> | |
| </div> | |
| <p class="text-gray-600 mb-4">Reinforce your learning with random quizzes from all subjects.</p> | |
| <div class="flex justify-between items-center"> | |
| <div class="flex"> | |
| <i class="fas fa-star text-yellow-400 mr-1"></i> | |
| <i class="fas fa-star text-yellow-400 mr-1"></i> | |
| <i class="fas fa-star text-yellow-400 mr-1"></i> | |
| <i class="fas fa-star text-yellow-400 mr-1"></i> | |
| <i class="fas fa-star text-yellow-400"></i> | |
| </div> | |
| <button class="bg-gradient-to-r from-purple-500 to-pink-500 text-white px-4 py-2 rounded-lg hover:opacity-90 transition duration-300"> | |
| Practice | |
| </button> | |
| </div> | |
| </div> | |
| `; | |
| container.appendChild(practiceCard); | |
| // Add event listeners to subject buttons | |
| document.querySelectorAll('.start-subject-btn').forEach(btn => { | |
| btn.addEventListener('click', async function() { | |
| const subjectId = this.dataset.subjectId; | |
| const subject = subjects.find(s => s.id == subjectId); | |
| // Show loading state | |
| this.innerHTML = '<i class="fas fa-spinner fa-spin mr-1"></i> Starting...'; | |
| try { | |
| const response = await mockAPI.startSubjectLesson(mockDatabase.currentUser.id, subjectId); | |
| if (response.success) { | |
| // In a real app, we would redirect to the lesson page | |
| alert(`Starting ${subject.name} lesson!`); | |
| } | |
| } catch (error) { | |
| console.error("Error starting lesson:", error); | |
| alert("Failed to start lesson. Please try again."); | |
| } finally { | |
| // Reset button text | |
| this.textContent = 'Start'; | |
| } | |
| }); | |
| }); | |
| } catch (error) { | |
| console.error("Error loading subjects:", error); | |
| document.getElementById('subjectsContainer').innerHTML = ` | |
| <div class="text-center py-8 col-span-3"> | |
| <i class="fas fa-exclamation-triangle text-red-500 text-3xl mb-3"></i> | |
| <p class="text-gray-600">Failed to load subjects. Please try again later.</p> | |
| <button class="mt-4 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition duration-300" onclick="loadSubjects()"> | |
| Retry | |
| </button> | |
| </div> | |
| `; | |
| } | |
| } | |
| // Load leaderboard | |
| async function loadLeaderboard() { | |
| try { | |
| const leaderboard = await mockAPI.getLeaderboard(); | |
| const container = document.getElementById('leaderboardBody'); | |
| // Clear loading state | |
| container.innerHTML = ''; | |
| // Add each leaderboard entry | |
| leaderboard.forEach((user, index) => { | |
| const row = document.createElement('tr'); | |
| row.className = 'hover:bg-gray-50'; | |
| // Determine rank color | |
| let rankClass = 'bg-gray-300'; | |
| let rankTextColor = 'text-white'; | |
| if (index === 0) { | |
| rankClass = 'bg-yellow-400'; | |
| rankTextColor = 'text-white'; | |
| } else if (index === 1) { | |
| rankClass = 'bg-gray-300'; | |
| rankTextColor = 'text-white'; | |
| } else if (index === 2) { | |
| rankClass = 'bg-amber-600'; | |
| rankTextColor = 'text-white'; | |
| } | |
| row.innerHTML = ` | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="w-8 h-8 rounded-full ${rankClass} flex items-center justify-center ${rankTextColor} font-bold">${index + 1}</div> | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 h-10 w-10"> | |
| <img class="h-10 w-10 rounded-full" src="${user.avatar}" alt=""> | |
| </div> | |
| <div class="ml-4"> | |
| <div class="text-sm font-medium text-gray-900">${user.name}</div> | |
| <div class="text-sm text-gray-500">${user.title}</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <div class="text-sm text-gray-900">${user.xp.toLocaleString()}</div> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap"> | |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">${user.level}</span> | |
| </td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-fire text-red-500 mr-1"></i> | |
| <span>${user.streak} days</span> | |
| </div> | |
| </td> | |
| `; | |
| container.appendChild(row); | |
| }); | |
| } catch (error) { | |
| console.error("Error loading leaderboard:", error); | |
| document.getElementById('leaderboardBody').innerHTML = ` | |
| <tr> | |
| <td colspan="5" class="px-6 py-4 text-center"> | |
| <i class="fas fa-exclamation-triangle text-red-500 text-3xl mb-3"></i> | |
| <p class="mt-2 text-gray-600">Failed to load leaderboard. Please try again later.</p> | |
| <button class="mt-4 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition duration-300" onclick="loadLeaderboard()"> | |
| Retry | |
| </button> | |
| </td> | |
| </tr> | |
| `; | |
| } | |
| } | |
| // Load badges | |
| async function loadBadges() { | |
| try { | |
| const badges = await mockAPI.getBadges(mockDatabase.currentUser.id); | |
| const container = document.getElementById('badgesContainer'); | |
| // Clear loading state | |
| container.innerHTML = ''; | |
| // Add each badge | |
| badges.forEach(badge => { | |
| const badgeCard = document.createElement('div'); | |
| badgeCard.className = `bg-white rounded-xl shadow-md p-4 text-center ${badge.earned ? '' : 'opacity-70'}`; | |
| badgeCard.innerHTML = ` | |
| <div class="w-16 h-16 mx-auto mb-3 ${badge.earned ? `bg-${badge.color}-100` : 'bg-gray-200'} rounded-full flex items-center justify-center ${badge.earned ? `text-${badge.color}-500` : 'text-gray-400'} text-2xl"> | |
| <i class="fas fa-${badge.icon}"></i> | |
| </div> | |
| <h3 class="font-bold text-sm mb-1 ${badge.earned ? '' : 'text-gray-400'}">${badge.name}</h3> | |
| <p class="text-xs ${badge.earned ? 'text-gray-500' : 'text-gray-400'}">${badge.description}</p> | |
| `; | |
| container.appendChild(badgeCard); | |
| }); | |
| } catch (error) { | |
| console.error("Error loading badges:", error); | |
| document.getElementById('badgesContainer').innerHTML = ` | |
| <div class="text-center py-8 col-span-6"> | |
| <i class="fas fa-exclamation-triangle text-red-500 text-3xl mb-3"></i> | |
| <p class="mt-4 text-gray-600">Failed to load badges. Please try again later.</p> | |
| <button class="mt-4 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition duration-300" onclick="loadBadges()"> | |
| Retry | |
| </button> | |
| </div> | |
| `; | |
| } | |
| } | |
| // Load discussions | |
| async function loadDiscussions() { | |
| try { | |
| const discussions = await mockAPI.getDiscussions(); | |
| const container = document.getElementById('discussionsContainer'); | |
| // Clear loading state | |
| container.innerHTML = ''; | |
| // Add each discussion | |
| discussions.forEach((discussion, index) => { | |
| const discussionItem = document.createElement('div'); | |
| discussionItem.className = `border-b border-gray-200 pb-4 ${index === discussions.length - 1 ? 'border-b-0' : ''}`; | |
| discussionItem.innerHTML = ` | |
| <div class="flex items-start"> | |
| <div class="flex-shrink-0 mr-4"> | |
| <img class="h-10 w-10 rounded-full" src="${discussion.userAvatar}" alt=""> | |
| </div> | |
| <div class="flex-1 min-w-0"> | |
| <p class="text-sm font-medium text-gray-900"> | |
| <a href="#" class="hover:underline">${discussion.title}</a> | |
| </p> | |
| <p class="text-sm text-gray-500 truncate">${discussion.content}</p> | |
| <div class="mt-2 flex items-center text-xs text-gray-500"> | |
| <span class="mr-3">Posted by ${discussion.userName} ${discussion.time}</span> | |
| <span class="mr-3"><i class="fas fa-comment mr-1"></i> ${discussion.replies} answers</span> | |
| <span><i class="fas fa-heart mr-1 text-red-500"></i> ${discussion.likes}</span> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| container.appendChild(discussionItem); | |
| }); | |
| } catch (error) { | |
| console.error("Error loading discussions:", error); | |
| document.getElementById('discussionsContainer').innerHTML = ` | |
| <div class="text-center py-8"> | |
| <i class="fas fa-exclamation-triangle text-red-500 text-3xl mb-3"></i> | |
| <p class="mt-4 text-gray-600">Failed to load discussions. Please try again later.</p> | |
| <button class="mt-4 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition duration-300" onclick="loadDiscussions()"> | |
| Retry | |
| </button> | |
| </div> | |
| `; | |
| } | |
| } | |
| // Load daily challenge | |
| async function loadDailyChallenge() { | |
| try { | |
| const challenge = await mockAPI.getDailyChallenge(); | |
| document.getElementById('challengeQuestion').textContent = challenge.question; | |
| document.getElementById('challengeText').textContent = challenge.challenge; | |
| // Handle challenge submission | |
| document.getElementById('submitChallengeBtn').addEventListener('click', async function() { | |
| const answer = document.getElementById('challengeAnswer').value.trim(); | |
| const feedback = document.getElementById('challengeFeedback'); | |
| if (!answer) { | |
| feedback.textContent = "Please enter an answer"; | |
| feedback.className = "text-sm mt-2 text-red-500"; | |
| feedback.classList.remove('hidden'); | |
| return; | |
| } | |
| // Show loading state | |
| this.innerHTML = '<i class="fas fa-spinner fa-spin mr-1"></i> Checking...'; | |
| try { | |
| const response = await mockAPI.submitChallengeAnswer( | |
| mockDatabase.currentUser.id, | |
| challenge.id, | |
| answer | |
| ); | |
| if (response.success) { | |
| feedback.textContent = `Correct! +${challenge.xpReward} XP earned. Your streak is now ${response.streak} days.`; | |
| feedback.className = "text-sm mt-2 text-green-500"; | |
| // Update user stats in UI | |
| document.getElementById('streakCount').textContent = response.streak; | |
| document.getElementById('xpCount').textContent = response.userXp.toLocaleString(); | |
| document.getElementById('currentLevel').textContent = response.userLevel; | |
| document.getElementById('progressPercent').textContent = response.userLevelProgress; | |
| document.getElementById('levelProgressBar').style.width = `${response.userLevelProgress}%`; | |
| // Disable the input and button | |
| document.getElementById('challengeAnswer').disabled = true; | |
| this.disabled = true; | |
| this.classList.remove('pulse-animation'); | |
| this.classList.add('bg-green-500'); | |
| this.innerHTML = '<i class="fas fa-check mr-1"></i> Completed'; | |
| } else { | |
| feedback.textContent = `Incorrect. The correct answer is ${response.correctAnswer}. Try again tomorrow!`; | |
| feedback.className = "text-sm mt-2 text-red-500"; | |
| } | |
| feedback.classList.remove('hidden'); | |
| } catch (error) { | |
| console.error("Error submitting challenge:", error); | |
| feedback.textContent = "An error occurred. Please try again."; | |
| feedback.className = "text-sm mt-2 text-red-500"; | |
| feedback.classList.remove('hidden'); | |
| } finally { | |
| if (!this.disabled) { | |
| this.textContent = 'Submit'; | |
| } | |
| } | |
| }); | |
| } catch (error) { | |
| console.error("Error loading daily challenge:", error); | |
| document.getElementById('challengeQuestion').textContent = "Daily Challenge"; | |
| document.getElementById('challengeText').textContent = "Failed to load today's challenge. Please check back later."; | |
| document.getElementById('challengeAnswer').disabled = true; | |
| document.getElementById('submitChallengeBtn').disabled = true; | |
| } | |
| } | |
| // Start learning button | |
| document.getElementById('startLearningBtn').addEventListener('click', function() { | |
| // Scroll to subjects section | |
| document.getElementById('courses').scrollIntoView({ behavior: 'smooth' }); | |
| }); | |
| // Load all data when page loads | |
| await Promise.all([ | |
| loadUserData(), | |
| loadSubjects(), | |
| loadLeaderboard(), | |
| loadBadges(), | |
| loadDiscussions(), | |
| loadDailyChallenge() | |
| ]); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=wasikherro/edu" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |