edu / index.html
wasikherro's picture
Add 2 files
8d4a4ce verified
<!DOCTYPE html>
<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>