Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>EduLoom - Modern AI-Ready Learning Platform</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.14.1/cdn.min.js" defer></script> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet"> | |
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); | |
body { | |
font-family: 'Inter', sans-serif; | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
min-height: 100vh; | |
} | |
.glass-effect { | |
background: rgba(255, 255, 255, 0.1); | |
backdrop-filter: blur(10px); | |
border: 1px solid rgba(255, 255, 255, 0.2); | |
} | |
.gradient-text { | |
background: linear-gradient(45deg, #667eea, #764ba2); | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
background-clip: text; | |
} | |
.hover-scale { | |
transition: transform 0.3s ease; | |
} | |
.hover-scale:hover { | |
transform: translateY(-5px) scale(1.02); | |
} | |
.pulse-animation { | |
animation: pulse 2s infinite; | |
} | |
@keyframes pulse { | |
0% { opacity: 1; } | |
50% { opacity: 0.7; } | |
100% { opacity: 1; } | |
} | |
.slide-in { | |
animation: slideIn 0.5s ease-out; | |
} | |
@keyframes slideIn { | |
from { transform: translateY(20px); opacity: 0; } | |
to { transform: translateY(0); opacity: 1; } | |
} | |
.typing-effect { | |
border-right: 2px solid #667eea; | |
animation: blink 1s infinite; | |
} | |
@keyframes blink { | |
0%, 50% { border-color: #667eea; } | |
51%, 100% { border-color: transparent; } | |
} | |
.course-card { | |
background: linear-gradient(135deg, rgba(255,255,255,0.1), rgba(255,255,255,0.05)); | |
border: 1px solid rgba(255,255,255,0.2); | |
transition: all 0.3s ease; | |
} | |
.course-card:hover { | |
transform: translateY(-8px); | |
box-shadow: 0 20px 40px rgba(0,0,0,0.3); | |
} | |
.progress-ring { | |
transform: rotate(-90deg); | |
} | |
.progress-ring__circle { | |
transition: stroke-dashoffset 0.35s; | |
stroke: #667eea; | |
stroke-width: 4; | |
fill: transparent; | |
stroke-dasharray: 251.2; | |
stroke-dashoffset: 251.2; | |
} | |
.floating-nav { | |
position: fixed; | |
top: 50%; | |
right: 2rem; | |
transform: translateY(-50%); | |
z-index: 1000; | |
} | |
.nav-dot { | |
width: 12px; | |
height: 12px; | |
border-radius: 50%; | |
background: rgba(255,255,255,0.5); | |
margin: 10px 0; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
} | |
.nav-dot.active { | |
background: #667eea; | |
transform: scale(1.5); | |
} | |
.video-container { | |
position: relative; | |
overflow: hidden; | |
border-radius: 20px; | |
box-shadow: 0 10px 30px rgba(0,0,0,0.3); | |
} | |
.quiz-option { | |
transition: all 0.3s ease; | |
cursor: pointer; | |
} | |
.quiz-option:hover { | |
background: rgba(102, 126, 234, 0.2); | |
transform: translateX(5px); | |
} | |
.quiz-option.selected { | |
background: rgba(102, 126, 234, 0.3); | |
border-color: #667eea; | |
} | |
.quiz-option.correct { | |
background: rgba(34, 197, 94, 0.3); | |
border-color: #22c55e; | |
} | |
.quiz-option.incorrect { | |
background: rgba(239, 68, 68, 0.3); | |
border-color: #ef4444; | |
} | |
.modal-backdrop { | |
background: rgba(0, 0, 0, 0.8); | |
backdrop-filter: blur(5px); | |
} | |
.modal-content { | |
transform: scale(0.9); | |
transition: transform 0.3s ease; | |
} | |
.modal-content.show { | |
transform: scale(1); | |
} | |
.notification { | |
position: fixed; | |
top: 20px; | |
right: 20px; | |
z-index: 1001; | |
animation: slideInRight 0.5s ease; | |
} | |
@keyframes slideInRight { | |
from { transform: translateX(100%); opacity: 0; } | |
to { transform: translateX(0); opacity: 1; } | |
} | |
.search-bar { | |
background: rgba(255,255,255,0.1); | |
border: 1px solid rgba(255,255,255,0.2); | |
transition: all 0.3s ease; | |
} | |
.search-bar:focus { | |
background: rgba(255,255,255,0.2); | |
border-color: #667eea; | |
box-shadow: 0 0 20px rgba(102, 126, 234, 0.3); | |
} | |
.category-pill { | |
background: rgba(255,255,255,0.1); | |
border: 1px solid rgba(255,255,255,0.2); | |
transition: all 0.3s ease; | |
} | |
.category-pill:hover, | |
.category-pill.active { | |
background: rgba(102, 126, 234, 0.3); | |
border-color: #667eea; | |
transform: translateY(-2px); | |
} | |
.instructor-avatar { | |
width: 60px; | |
height: 60px; | |
border-radius: 50%; | |
border: 3px solid #667eea; | |
background: linear-gradient(135deg, #667eea, #764ba2); | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
color: white; | |
font-weight: bold; | |
font-size: 1.2rem; | |
} | |
.rating-stars { | |
color: #fbbf24; | |
} | |
.progress-bar { | |
background: rgba(255,255,255,0.1); | |
border-radius: 10px; | |
overflow: hidden; | |
} | |
.progress-fill { | |
height: 100%; | |
background: linear-gradient(90deg, #667eea, #764ba2); | |
transition: width 0.5s ease; | |
} | |
.ai-chat { | |
position: fixed; | |
bottom: 20px; | |
right: 20px; | |
width: 350px; | |
height: 500px; | |
background: rgba(255,255,255,0.1); | |
backdrop-filter: blur(20px); | |
border: 1px solid rgba(255,255,255,0.2); | |
border-radius: 20px; | |
overflow: hidden; | |
transition: all 0.3s ease; | |
} | |
.ai-chat.minimized { | |
height: 60px; | |
width: 200px; | |
} | |
.chat-messages { | |
height: calc(100% - 120px); | |
overflow-y: auto; | |
padding: 10px; | |
} | |
.chat-message { | |
margin: 10px 0; | |
padding: 10px 15px; | |
border-radius: 15px; | |
max-width: 80%; | |
word-wrap: break-word; | |
} | |
.chat-message.user { | |
background: rgba(102, 126, 234, 0.3); | |
margin-left: auto; | |
} | |
.chat-message.ai { | |
background: rgba(255,255,255,0.1); | |
margin-right: auto; | |
} | |
.payment-modal { | |
background: rgba(255,255,255,0.05); | |
backdrop-filter: blur(20px); | |
border: 1px solid rgba(255,255,255,0.1); | |
} | |
.stripe-card { | |
background: linear-gradient(135deg, #667eea, #764ba2); | |
color: white; | |
padding: 20px; | |
border-radius: 15px; | |
margin: 10px 0; | |
} | |
</style> | |
</head> | |
<body class="bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900"> | |
<div x-data="eduLoomApp()" x-init="init()" class="min-h-screen"> | |
<!-- Navigation --> | |
<nav class="glass-effect fixed top-0 w-full z-50 px-6 py-4"> | |
<div class="max-w-7xl mx-auto flex justify-between items-center"> | |
<div class="flex items-center space-x-4"> | |
<h1 class="text-2xl font-bold text-white"> | |
<i class="fas fa-graduation-cap mr-2"></i>EduLoom | |
</h1> | |
</div> | |
<div class="hidden md:flex items-center space-x-6"> | |
<button @click="currentPage = 'home'" | |
:class="{'text-white': currentPage === 'home', 'text-gray-300': currentPage !== 'home'}" | |
class="hover:text-white transition">Home</button> | |
<button @click="currentPage = 'courses'" | |
:class="{'text-white': currentPage === 'courses', 'text-gray-300': currentPage !== 'courses'}" | |
class="hover:text-white transition">Courses</button> | |
<button @click="currentPage = 'dashboard'" | |
x-show="user" | |
:class="{'text-white': currentPage === 'dashboard', 'text-gray-300': currentPage !== 'dashboard'}" | |
class="hover:text-white transition">Dashboard</button> | |
<button @click="currentPage = 'instructor'" | |
x-show="user?.role === 'instructor'" | |
:class="{'text-white': currentPage === 'instructor', 'text-gray-300': currentPage !== 'instructor'}" | |
class="hover:text-white transition">Teach</button> | |
</div> | |
<div class="flex items-center space-x-4"> | |
<div class="relative"> | |
<input type="text" | |
x-model="searchQuery" | |
@input="searchCourses()" | |
placeholder="Search courses..." | |
class="search-bar rounded-full px-4 py-2 text-white placeholder-gray-300 w-48 md:w-64"> | |
<i class="fas fa-search absolute right-3 top-3 text-gray-300"></i> | |
</div> | |
<div x-show="!user" class="flex space-x-2"> | |
<button @click="openModal('login')" | |
class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-full transition"> | |
Login | |
</button> | |
<button @click="openModal('register')" | |
class="bg-gradient-to-r from-purple-500 to-blue-500 hover:from-purple-600 hover:to-blue-600 text-white px-4 py-2 rounded-full transition"> | |
Sign Up | |
</button> | |
</div> | |
<div x-show="user" class="flex items-center space-x-4"> | |
<button @click="toggleNotifications()" class="relative"> | |
<i class="fas fa-bell text-white text-xl"></i> | |
<span x-show="notifications.length > 0" | |
class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center"> | |
<span x-text="notifications.length"></span> | |
</span> | |
</button> | |
<div class="relative"> | |
<button @click="profileDropdown = !profileDropdown" | |
class="w-10 h-10 rounded-full bg-gradient-to-r from-purple-500 to-blue-500 flex items-center justify-center text-white"> | |
<span x-text="user?.name?.charAt(0)?.toUpperCase() || 'U'"></span> | |
</button> | |
<div x-show="profileDropdown" | |
@click.away="profileDropdown = false" | |
class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg py-2"> | |
<button @click="currentPage = 'profile'; profileDropdown = false" | |
class="block w-full text-left px-4 py-2 hover:bg-gray-100">Profile</button> | |
<button @click="logout()" | |
class="block w-full text-left px-4 py-2 hover:bg-gray-100 text-red-600">Logout</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</nav> | |
<!-- Floating Navigation --> | |
<div class="floating-nav hidden lg:block"> | |
<div class="nav-dot" :class="{'active': currentPage === 'home'}" @click="currentPage = 'home'"></div> | |
<div class="nav-dot" :class="{'active': currentPage === 'courses'}" @click="currentPage = 'courses'"></div> | |
<div class="nav-dot" :class="{'active': currentPage === 'dashboard'}" @click="currentPage = 'dashboard'" x-show="user"></div> | |
<div class="nav-dot" :class="{'active': currentPage === 'instructor'}" @click="currentPage = 'instructor'" x-show="user?.role === 'instructor'"></div> | |
</div> | |
<!-- Main Content --> | |
<main class="pt-20"> | |
<!-- Home Page --> | |
<div x-show="currentPage === 'home'" class="px-6 py-12"> | |
<div class="max-w-7xl mx-auto"> | |
<!-- Hero Section --> | |
<div class="text-center mb-16"> | |
<h1 class="text-5xl md:text-7xl font-bold text-white mb-6"> | |
Learn Without <span class="gradient-text">Limits</span> | |
</h1> | |
<p class="text-xl text-gray-300 mb-8 max-w-2xl mx-auto"> | |
Join millions of learners worldwide. Master new skills with AI-powered courses designed for your success. | |
</p> | |
<div class="flex justify-center space-x-4"> | |
<button @click="currentPage = 'courses'" | |
class="bg-gradient-to-r from-purple-500 to-blue-500 hover:from-purple-600 hover:to-blue-600 text-white px-8 py-4 rounded-full text-lg font-semibold transition transform hover:scale-105"> | |
Explore Courses | |
</button> | |
<button @click="openModal('register')" | |
class="bg-white/20 hover:bg-white/30 text-white px-8 py-4 rounded-full text-lg font-semibold transition"> | |
Start Free Trial | |
</button> | |
</div> | |
</div> | |
<!-- Stats --> | |
<div class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-16"> | |
<div class="glass-effect rounded-2xl p-6 text-center hover-scale"> | |
<div class="text-3xl font-bold text-white mb-2">50K+</div> | |
<div class="text-gray-300">Students</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center hover-scale"> | |
<div class="text-3xl font-bold text-white mb-2">1.2K+</div> | |
<div class="text-gray-300">Courses</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center hover-scale"> | |
<div class="text-3xl font-bold text-white mb-2">200+</div> | |
<div class="text-gray-300">Instructors</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center hover-scale"> | |
<div class="text-3xl font-bold text-white mb-2">95%</div> | |
<div class="text-gray-300">Success Rate</div> | |
</div> | |
</div> | |
<!-- Featured Courses --> | |
<div class="mb-16"> | |
<h2 class="text-3xl font-bold text-white mb-8">Featured Courses</h2> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-8"> | |
<template x-for="course in featuredCourses" :key="course.id"> | |
<div class="course-card rounded-2xl p-6 hover-scale cursor-pointer" @click="viewCourse(course)"> | |
<div class="relative mb-4"> | |
<img :src="course.thumbnail" :alt="course.title" class="w-full h-48 rounded-xl object-cover"> | |
<div class="absolute top-4 right-4 bg-green-500 text-white px-3 py-1 rounded-full text-sm"> | |
<span x-text="course.price === 0 ? 'FREE' : '$' + course.price"></span> | |
</div> | |
</div> | |
<h3 class="text-xl font-bold text-white mb-2" x-text="course.title"></h3> | |
<p class="text-gray-300 text-sm mb-3" x-text="course.description.substring(0, 80) + '...'"></p> | |
<div class="flex items-center justify-between"> | |
<div class="flex items-center"> | |
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-500 to-blue-500 flex items-center justify-center text-white text-sm mr-2"> | |
<span x-text="course.instructor.charAt(0)"></span> | |
</div> | |
<span class="text-gray-300 text-sm" x-text="course.instructor"></span> | |
</div> | |
<div class="flex items-center"> | |
<i class="fas fa-star text-yellow-400 mr-1"></i> | |
<span class="text-white" x-text="course.rating"></span> | |
</div> | |
</div> | |
</div> | |
</template> | |
</div> | |
</div> | |
<!-- Categories --> | |
<div class="mb-16"> | |
<h2 class="text-3xl font-bold text-white mb-8">Browse by Category</h2> | |
<div class="flex flex-wrap gap-4"> | |
<template x-for="category in categories" :key="category"> | |
<button @click="filterByCategory(category)" | |
class="category-pill px-6 py-3 rounded-full text-white transition"> | |
<span x-text="category"></span> | |
</button> | |
</template> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Courses Page --> | |
<div x-show="currentPage === 'courses'" class="px-6 py-12"> | |
<div class="max-w-7xl mx-auto"> | |
<h1 class="text-4xl font-bold text-white mb-8">Explore Courses</h1> | |
<!-- Filters --> | |
<div class="glass-effect rounded-2xl p-6 mb-8"> | |
<div class="grid grid-cols-1 md:grid-cols-4 gap-4"> | |
<select x-model="filters.level" class="search-bar rounded-lg px-4 py-2 text-white"> | |
<option value="">All Levels</option> | |
<option value="beginner">Beginner</option> | |
<option value="intermediate">Intermediate</option> | |
<option value="advanced">Advanced</option> | |
</select> | |
<select x-model="filters.price" class="search-bar rounded-lg px-4 py-2 text-white"> | |
<option value="">Any Price</option> | |
<option value="free">Free</option> | |
<option value="paid">Paid</option> | |
</select> | |
<select x-model="filters.rating" class="search-bar rounded-lg px-4 py-2 text-white"> | |
<option value="">Any Rating</option> | |
<option value="4">4+ Stars</option> | |
<option value="4.5">4.5+ Stars</option> | |
</select> | |
<button @click="resetFilters()" | |
class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition"> | |
Reset Filters | |
</button> | |
</div> | |
</div> | |
<!-- Course Grid --> | |
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-6"> | |
<template x-for="course in filteredCourses" :key="course.id"> | |
<div class="course-card rounded-2xl p-4 hover-scale cursor-pointer" @click="viewCourse(course)"> | |
<img :src="course.thumbnail" :alt="course.title" class="w-full h-40 rounded-xl object-cover mb-4"> | |
<h3 class="text-lg font-bold text-white mb-2" x-text="course.title"></h3> | |
<p class="text-gray-300 text-sm mb-2" x-text="course.instructor"></p> | |
<div class="flex items-center justify-between"> | |
<div class="flex items-center"> | |
<i class="fas fa-star text-yellow-400 mr-1"></i> | |
<span class="text-white text-sm" x-text="course.rating"></span> | |
</div> | |
<span class="text-white font-bold" x-text="course.price === 0 ? 'FREE' : '$' + course.price"></span> | |
</div> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> | |
<!-- Course Detail Page --> | |
<div x-show="currentPage === 'course-detail'" class="px-6 py-12"> | |
<div class="max-w-6xl mx-auto"> | |
<button @click="currentPage = 'courses'" class="text-white mb-6 flex items-center"> | |
<i class="fas fa-arrow-left mr-2"></i> Back to Courses | |
</button> | |
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
<!-- Main Content --> | |
<div class="lg:col-span-2"> | |
<!-- Video Player --> | |
<div class="video-container mb-6"> | |
<video :src="selectedCourse?.videoUrl" controls class="w-full h-96"> | |
Your browser does not support the video tag. | |
</video> | |
</div> | |
<!-- Course Info --> | |
<div class="glass-effect rounded-2xl p-6 mb-6"> | |
<h1 class="text-3xl font-bold text-white mb-4" x-text="selectedCourse?.title"></h1> | |
<p class="text-gray-300 mb-4" x-text="selectedCourse?.description"></p> | |
<div class="flex items-center space-x-4 mb-4"> | |
<div class="flex items-center"> | |
<div class="instructor-avatar mr-3"> | |
<span x-text="selectedCourse?.instructor?.charAt(0)"></span> | |
</div> | |
<div> | |
<div class="text-white font-semibold" x-text="selectedCourse?.instructor"></div> | |
<div class="text-gray-400 text-sm">Instructor</div> | |
</div> | |
</div> | |
<div class="flex items-center"> | |
<i class="fas fa-star text-yellow-400 mr-1"></i> | |
<span class="text-white" x-text="selectedCourse?.rating"></span> | |
<span class="text-gray-400 ml-1">(1,234 reviews)</span> | |
</div> | |
<div class="text-white"> | |
<span x-text="selectedCourse?.students + ' students'"></span> | |
</div> | |
</div> | |
<div class="flex items-center space-x-4"> | |
<button @click="enrollCourse(selectedCourse)" | |
x-show="!isEnrolled(selectedCourse?.id)" | |
class="bg-gradient-to-r from-purple-500 to-blue-500 hover:from-purple-600 hover:to-blue-600 text-white px-8 py-3 rounded-full font-semibold transition"> | |
Enroll Now | |
</button> | |
<button @click="toggleWishlist(selectedCourse)" | |
class="bg-white/20 hover:bg-white/30 text-white px-4 py-3 rounded-full transition"> | |
<i :class="isInWishlist(selectedCourse?.id) ? 'fas fa-heart text-red-500' : 'far fa-heart'"></i> | |
</button> | |
</div> | |
</div> | |
<!-- Course Content --> | |
<div class="glass-effect rounded-2xl p-6"> | |
<h2 class="text-2xl font-bold text-white mb-4">Course Content</h2> | |
<div class="space-y-4"> | |
<template x-for="section in selectedCourse?.sections" :key="section.id"> | |
<div> | |
<h3 class="text-lg font-semibold text-white mb-2" x-text="section.title"></h3> | |
<div class="space-y-2"> | |
<template x-for="lecture in section.lectures" :key="lecture.id"> | |
<div class="flex items-center justify-between p-3 bg-white/10 rounded-lg"> | |
<div class="flex items-center"> | |
<i :class="lecture.completed ? 'fas fa-check-circle text-green-400' : 'far fa-circle text-gray-400'" | |
class="mr-3"></i> | |
<span class="text-white" x-text="lecture.title"></span> | |
</div> | |
<span class="text-gray-400 text-sm" x-text="lecture.duration"></span> | |
</div> | |
</template> | |
</div> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> | |
<!-- Sidebar --> | |
<div class="space-y-6"> | |
<!-- Course Stats --> | |
<div class="glass-effect rounded-2xl p-6"> | |
<h3 class="text-xl font-bold text-white mb-4">Course Stats</h3> | |
<div class="space-y-4"> | |
<div> | |
<div class="flex justify-between text-white mb-1"> | |
<span>Progress</span> | |
<span x-text="getCourseProgress(selectedCourse?.id) + '%'"></span> | |
</div> | |
<div class="progress-bar h-2"> | |
<div class="progress-fill" :style="`width: ${getCourseProgress(selectedCourse?.id)}%`"></div> | |
</div> | |
</div> | |
<div class="text-gray-300"> | |
<i class="fas fa-clock mr-2"></i> | |
<span x-text="selectedCourse?.totalHours + ' hours'"></span> | |
</div> | |
<div class="text-gray-300"> | |
<i class="fas fa-certificate mr-2"></i> | |
<span>Certificate of Completion</span> | |
</div> | |
</div> | |
</div> | |
<!-- Discussion --> | |
<div class="glass-effect rounded-2xl p-6"> | |
<h3 class="text-xl font-bold text-white mb-4">Recent Discussions</h3> | |
<div class="space-y-4"> | |
<template x-for="comment in selectedCourse?.comments" :key="comment.id"> | |
<div class="border-b border-white/10 pb-3"> | |
<div class="flex items-center mb-2"> | |
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-500 to-blue-500 flex items-center justify-center text-white text-sm mr-2"> | |
<span x-text="comment.user.charAt(0)"></span> | |
</div> | |
<span class="text-white text-sm" x-text="comment.user"></span> | |
</div> | |
<p class="text-gray-300 text-sm" x-text="comment.text"></p> | |
</div> | |
</template> | |
</div> | |
<div class="mt-4"> | |
<textarea x-model="newComment" | |
placeholder="Ask a question..." | |
class="search-bar rounded-lg px-3 py-2 text-white w-full mb-2"></textarea> | |
<button @click="postComment()" | |
class="bg-gradient-to-r from-purple-500 to-blue-500 text-white px-4 py-2 rounded-lg w-full"> | |
Post Comment | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Dashboard --> | |
<div x-show="currentPage === 'dashboard'" class="px-6 py-12"> | |
<div class="max-w-7xl mx-auto"> | |
<h1 class="text-4xl font-bold text-white mb-8">My Dashboard</h1> | |
<!-- Stats Cards --> | |
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8"> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="text-3xl font-bold text-white mb-2" x-text="enrolledCourses.length"></div> | |
<div class="text-gray-300">Enrolled Courses</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="text-3xl font-bold text-white mb-2" x-text="completedCourses.length"></div> | |
<div class="text-gray-300">Completed</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="text-3xl font-bold text-white mb-2" x-text="certificatesEarned"></div> | |
<div class="text-gray-300">Certificates</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="text-3xl font-bold text-white mb-2" x-text="totalHours"></div> | |
<div class="text-gray-300">Hours Learned</div> | |
</div> | |
</div> | |
<!-- My Courses --> | |
<div class="glass-effect rounded-2xl p-6 mb-8"> | |
<h2 class="text-2xl font-bold text-white mb-4">My Courses</h2> | |
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> | |
<template x-for="course in enrolledCourses" :key="course.id"> | |
<div class="course-card rounded-xl p-4"> | |
<img :src="course.thumbnail" :alt="course.title" class="w-full h-32 rounded-lg object-cover mb-3"> | |
<h3 class="text-white font-semibold mb-2" x-text="course.title"></h3> | |
<div class="mb-3"> | |
<div class="flex justify-between text-sm text-gray-300 mb-1"> | |
<span>Progress</span> | |
<span x-text="getCourseProgress(course.id) + '%'"></span> | |
</div> | |
<div class="progress-bar h-2"> | |
<div class="progress-fill" :style="`width: ${getCourseProgress(course.id)}%`"></div> | |
</div> | |
</div> | |
<button @click="currentPage = 'course-detail'; selectedCourse = course" | |
class="w-full bg-gradient-to-r from-purple-500 to-blue-500 text-white py-2 rounded-lg"> | |
Continue Learning | |
</button> | |
</div> | |
</template> | |
</div> | |
</div> | |
<!-- Achievements --> | |
<div class="glass-effect rounded-2xl p-6"> | |
<h2 class="text-2xl font-bold text-white mb-4">Achievements</h2> | |
<div class="grid grid-cols-2 md:grid-cols-4 gap-4"> | |
<template x-for="badge in achievements" :key="badge.id"> | |
<div class="text-center"> | |
<div class="w-16 h-16 mx-auto mb-2 bg-gradient-to-r from-purple-500 to-blue-500 rounded-full flex items-center justify-center"> | |
<i :class="badge.icon" class="text-white text-2xl"></i> | |
</div> | |
<div class="text-white text-sm" x-text="badge.name"></div> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Instructor Dashboard --> | |
<div x-show="currentPage === 'instructor'" class="px-6 py-12"> | |
<div class="max-w-7xl mx-auto"> | |
<h1 class="text-4xl font-bold text-white mb-8">Instructor Dashboard</h1> | |
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
<!-- Stats --> | |
<div class="lg:col-span-2"> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="text-3xl font-bold text-white mb-2" x-text="publishedCourses.length"></div> | |
<div class="text-gray-300">Published Courses</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="text-3xl font-bold text-white mb-2" x-text="totalStudents"></div> | |
<div class="text-gray-300">Total Students</div> | |
</div> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="text-3xl font-bold text-white mb-2">$<span x-text="totalRevenue"></span></div> | |
<div class="text-gray-300">Total Revenue</div> | |
</div> | |
</div> | |
<!-- Create Course --> | |
<div class="glass-effect rounded-2xl p-6"> | |
<h2 class="text-2xl font-bold text-white mb-4">Create New Course</h2> | |
<form @submit.prevent="createCourse()" class="space-y-4"> | |
<div> | |
<label class="text-white mb-2 block">Course Title</label> | |
<input type="text" x-model="newCourse.title" | |
class="search-bar rounded-lg px-4 py-2 text-white w-full"> | |
</div> | |
<div> | |
<label class="text-white mb-2 block">Description</label> | |
<textarea x-model="newCourse.description" | |
class="search-bar rounded-lg px-4 py-2 text-white w-full h-24"></textarea> | |
</div> | |
<div class="grid grid-cols-2 gap-4"> | |
<div> | |
<label class="text-white mb-2 block">Category</label> | |
<select x-model="newCourse.category" class="search-bar rounded-lg px-4 py-2 text-white w-full"> | |
<option value="">Select Category</option> | |
<template x-for="category in categories" :key="category"> | |
<option :value="category" x-text="category"></option> | |
</template> | |
</select> | |
</div> | |
<div> | |
<label class="text-white mb-2 block">Price ($)</label> | |
<input type="number" x-model="newCourse.price" | |
class="search-bar rounded-lg px-4 py-2 text-white w-full"> | |
</div> | |
</div> | |
<button type="submit" | |
class="bg-gradient-to-r from-purple-500 to-blue-500 text-white px-6 py-2 rounded-lg"> | |
Create Course | |
</button> | |
</form> | |
</div> | |
</div> | |
<!-- My Courses --> | |
<div> | |
<div class="glass-effect rounded-2xl p-6"> | |
<h2 class="text-xl font-bold text-white mb-4">My Courses</h2> | |
<div class="space-y-4"> | |
<template x-for="course in publishedCourses" :key="course.id"> | |
<div class="flex items-center space-x-3"> | |
<img :src="course.thumbnail" class="w-12 h-12 rounded-lg object-cover"> | |
<div> | |
<div class="text-white font-semibold" x-text="course.title"></div> | |
<div class="text-gray-400 text-sm" x-text="course.students + ' students'"></div> | |
</div> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Profile Page --> | |
<div x-show="currentPage === 'profile'" class="px-6 py-12"> | |
<div class="max-w-4xl mx-auto"> | |
<h1 class="text-4xl font-bold text-white mb-8">Profile Settings</h1> | |
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
<div class="lg:col-span-2"> | |
<div class="glass-effect rounded-2xl p-6"> | |
<h2 class="text-2xl font-bold text-white mb-4">Personal Information</h2> | |
<form @submit.prevent="updateProfile()" class="space-y-4"> | |
<div class="grid grid-cols-2 gap-4"> | |
<div> | |
<label class="text-white mb-2 block">First Name</label> | |
<input type="text" x-model="userProfile.firstName" | |
class="search-bar rounded-lg px-4 py-2 text-white w-full"> | |
</div> | |
<div> | |
<label class="text-white mb-2 block">Last Name</label> | |
<input type="text" x-model="userProfile.lastName" | |
class="search-bar rounded-lg px-4 py-2 text-white w-full"> | |
</div> | |
</div> | |
<div> | |
<label class="text-white mb-2 block">Email</label> | |
<input type="email" x-model="userProfile.email" | |
class="search-bar rounded-lg px-4 py-2 text-white w-full"> | |
</div> | |
<div> | |
<label class="text-white mb-2 block">Bio</label> | |
<textarea x-model="userProfile.bio" | |
class="search-bar rounded-lg px-4 py-2 text-white w-full h-24"></textarea> | |
</div> | |
<button type="submit" | |
class="bg-gradient-to-r from-purple-500 to-blue-500 text-white px-6 py-2 rounded-lg"> | |
Save Changes | |
</button> | |
</form> | |
</div> | |
</div> | |
<div> | |
<div class="glass-effect rounded-2xl p-6 text-center"> | |
<div class="w-24 h-24 mx-auto mb-4 rounded-full bg-gradient-to-r from-purple-500 to-blue-500 flex items-center justify-center"> | |
<span class="text-white text-3xl font-bold" x-text="user?.name?.charAt(0)"></span> | |
</div> | |
<h3 class="text-xl font-bold text-white" x-text="user?.name"></h3> | |
<p class="text-gray-300" x-text="user?.email"></p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</main> | |
<!-- Modals --> | |
<div x-show="showModal" | |
x-transition:enter="transition ease-out duration-300" | |
x-transition:enter-start="opacity-0" | |
x-transition:enter-end="opacity-100" | |
x-transition:leave="transition ease-in duration-200" | |
x-transition:leave-start="opacity-100" | |
x-transition:leave-end="opacity-0" | |
class="fixed inset-0 modal-backdrop flex items-center justify-center z-50"> | |
<div class="modal-content bg-white rounded-2xl p-8 max-w-md w-full mx-4" | |
:class="{'show': showModal}"> | |
<button @click="closeModal()" class="absolute top-4 right-4 text-gray-500 hover:text-gray-700"> | |
<i class="fas fa-times text-xl"></i> | |
</button> | |
<!-- Login Modal --> | |
<div x-show="modalType === 'login'"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6 text-center">Welcome Back</h2> | |
<form @submit.prevent="login()" class="space-y-4"> | |
<div> | |
<label class="block text-gray-700 mb-2">Email</label> | |
<input type="email" x-model="loginForm.email" | |
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:border-purple-500"> | |
</div> | |
<div> | |
<label class="block text-gray-700 mb-2">Password</label> | |
<input type="password" x-model="loginForm.password" | |
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:border-purple-500"> | |
</div> | |
<button type="submit" | |
class="w-full bg-gradient-to-r from-purple-500 to-blue-500 text-white py-3 rounded-lg font-semibold"> | |
Sign In | |
</button> | |
</form> | |
<div class="text-center mt-4"> | |
<button @click="modalType = 'register'" class="text-purple-600 hover:underline"> | |
Don't have an account? Sign up | |
</button> | |
</div> | |
</div> | |
<!-- Register Modal --> | |
<div x-show="modalType === 'register'"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6 text-center">Join EduLoom</h2> | |
<form @submit.prevent="register()" class="space-y-4"> | |
<div> | |
<label class="block text-gray-700 mb-2">Full Name</label> | |
<input type="text" x-model="registerForm.name" | |
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:border-purple-500"> | |
</div> | |
<div> | |
<label class="block text-gray-700 mb-2">Email</label> | |
<input type="email" x-model="registerForm.email" | |
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:border-purple-500"> | |
</div> | |
<div> | |
<label class="block text-gray-700 mb-2">Password</label> | |
<input type="password" x-model="registerForm.password" | |
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:border-purple-500"> | |
</div> | |
<div> | |
<label class="block text-gray-700 mb-2">I want to</label> | |
<select x-model="registerForm.role" | |
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:border-purple-500"> | |
<option value="student">Learn</option> | |
<option value="instructor">Teach</option> | |
</select> | |
</div> | |
<button type="submit" | |
class="w-full bg-gradient-to-r from-purple-500 to-blue-500 text-white py-3 rounded-lg font-semibold"> | |
Create Account | |
</button> | |
</form> | |
<div class="text-center mt-4"> | |
<button @click="modalType = 'login'" class="text-purple-600 hover:underline"> | |
Already have an account? Sign in | |
</button> | |
</div> | |
</div> | |
<!-- Payment Modal --> | |
<div x-show="modalType === 'payment'"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6 text-center">Complete Your Purchase</h2> | |
<div class="payment-modal rounded-2xl p-6"> | |
<div class="text-center mb-4"> | |
<h3 class="text-xl font-bold text-white" x-text="selectedCourse?.title"></h3> | |
<p class="text-3xl font-bold text-white mt-2">$<span x-text="selectedCourse?.price"></span></p> | |
</div> | |
<form @submit.prevent="processPayment()" class="space-y-4"> | |
<div class="stripe-card"> | |
<div class="mb-4"> | |
<label class="text-white mb-2 block">Card Number</label> | |
<input type="text" placeholder="1234 5678 9012 3456" | |
class="w-full px-4 py-2 bg-white/20 border border-white/30 rounded-lg text-white placeholder-white/70"> | |
</div> | |
<div class="grid grid-cols-2 gap-4"> | |
<div> | |
<label class="text-white mb-2 block">Expiry</label> | |
<input type="text" placeholder="MM/YY" | |
class="w-full px-4 py-2 bg-white/20 border border-white/30 rounded-lg text-white placeholder-white/70"> | |
</div> | |
<div> | |
<label class="text-white mb-2 block">CVC</label> | |
<input type="text" placeholder="123" | |
class="w-full px-4 py-2 bg-white/20 border border-white/30 rounded-lg text-white placeholder-white/70"> | |
</div> | |
</div> | |
</div> | |
<button type="submit" | |
class="w-full bg-white text-purple-600 py-3 rounded-lg font-semibold"> | |
Complete Purchase | |
</button> | |
</form> | |
</div> | |
</div> | |
<!-- Quiz Modal --> | |
<div x-show="modalType === 'quiz'" class="max-w-2xl"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6 text-center">Quiz Time!</h2> | |
<div class="space-y-6"> | |
<div class="text-center"> | |
<h3 class="text-xl font-bold text-gray-800 mb-2" x-text="currentQuiz?.title"></h3> | |
<p class="text-gray-600">Question <span x-text="currentQuestionIndex + 1"></span> of <span x-text="currentQuiz?.questions?.length"></span></p> | |
</div> | |
<div class="bg-gray-50 rounded-lg p-6"> | |
<h4 class="text-lg font-semibold text-gray-800 mb-4" x-text="currentQuestion?.question"></h4> | |
<div class="space-y-3"> | |
<template x-for="(option, index) in currentQuestion?.options" :key="index"> | |
<div @click="selectAnswer(index)" | |
class="quiz-option p-4 border-2 border-gray-200 rounded-lg" | |
:class="{ | |
'selected': selectedAnswer === index, | |
'correct': showAnswer && index === currentQuestion?.correctAnswer, | |
'incorrect': showAnswer && selectedAnswer === index && index !== currentQuestion?.correctAnswer | |
}"> | |
<span x-text="option"></span> | |
</div> | |
</template> | |
</div> | |
</div> | |
<div class="flex justify-between"> | |
<button @click="previousQuestion()" | |
:disabled="currentQuestionIndex === 0" | |
class="bg-gray-200 text-gray-700 px-6 py-2 rounded-lg disabled:opacity-50"> | |
Previous | |
</button> | |
<button @click="nextQuestion()" | |
x-show="!showAnswer" | |
:disabled="selectedAnswer === null" | |
class="bg-gradient-to-r from-purple-500 to-blue-500 text-white px-6 py-2 rounded-lg disabled:opacity-50"> | |
Next | |
</button> | |
<button @click="submitQuiz()" | |
x-show="showAnswer && currentQuestionIndex === currentQuiz?.questions?.length - 1" | |
class="bg-green-500 text-white px-6 py-2 rounded-lg"> | |
Finish Quiz | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Notifications --> | |
<div class="notification" x-show="showNotification"> | |
<div class="glass-effect rounded-lg p-4 text-white"> | |
<div class="flex items-center"> | |
<i :class="notificationType === 'success' ? 'fas fa-check-circle text-green-400' : 'fas fa-exclamation-circle text-red-400'" | |
class="mr-2"></i> | |
<span x-text="notificationMessage"></span> | |
</div> | |
</div> | |
</div> | |
<!-- AI Chat Assistant --> | |
<div class="ai-chat" :class="{'minimized': !chatOpen}"> | |
<div class="bg-white/10 p-4 flex justify-between items-center"> | |
<h3 class="text-white font-semibold">AI Assistant</h3> | |
<button @click="chatOpen = !chatOpen" class="text-white"> | |
<i :class="chatOpen ? 'fas fa-minus' : 'fas fa-plus'"></i> | |
</button> | |
</div> | |
<div x-show="chatOpen" class="chat-messages"> | |
<template x-for="message in chatMessages" :key="message.id"> | |
<div :class="{'chat-message user': message.type === 'user', 'chat-message ai': message.type === 'ai'}" | |
x-text="message.text"> | |
</div> | |
</template> | |
</div> | |
<div x-show="chatOpen" class="p-4"> | |
<input type="text" | |
x-model="chatInput" | |
@keyup.enter="sendChatMessage()" | |
placeholder="Ask me anything..." | |
class="w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-300"> | |
</div> | |
</div> | |
<!-- Loading Spinner --> | |
<div x-show="loading" | |
class="fixed inset-0 bg-black/50 flex items-center justify-center z-50"> | |
<div class="w-16 h-16 border-4 border-purple-500 border-t-transparent rounded-full animate-spin"></div> | |
</div> | |
</div> | |
<script> | |
function eduLoomApp() { | |
return { | |
currentPage: 'home', | |
user: null, | |
userProfile: { | |
firstName: '', | |
lastName: '', | |
email: '', | |
bio: '' | |
}, | |
showModal: false, | |
modalType: 'login', | |
loading: false, | |
searchQuery: '', | |
filters: { | |
level: '', | |
price: '', | |
rating: '' | |
}, | |
courses: [], | |
featuredCourses: [], | |
enrolledCourses: [], | |
completedCourses: [], | |
certificatesEarned: 0, | |
totalHours: 0, | |
totalStudents: 0, | |
totalRevenue: 0, | |
publishedCourses: [], | |
achievements: [], | |
notifications: [], | |
showNotification: false, | |
notificationMessage: '', | |
notificationType: 'success', | |
profileDropdown: false, | |
selectedCourse: null, | |
newComment: '', | |
newCourse: { | |
title: '', | |
description: '', | |
category: '', | |
price: 0 | |
}, | |
loginForm: { | |
email: '', | |
password: '' | |
}, | |
registerForm: { | |
name: '', | |
email: '', | |
password: '', | |
role: 'student' | |
}, | |
chatOpen: false, | |
chatInput: '', | |
chatMessages: [], | |
currentQuiz: null, | |
currentQuestionIndex: 0, | |
currentQuestion: null, | |
selectedAnswer: null, | |
showAnswer: false, | |
wishlist: [], | |
categories: [ | |
'Web Development', | |
'Data Science', | |
'AI & Machine Learning', | |
'Mobile Development', | |
'Cloud Computing', | |
'Cybersecurity', | |
'Digital Marketing', | |
'Business' | |
], | |
init() { | |
// Initialize mock data | |
this.loadMockData(); | |
// Check for user in localStorage | |
const savedUser = localStorage.getItem('eduLoomUser'); | |
if (savedUser) { | |
this.user = JSON.parse(savedUser); | |
} | |
// Initialize achievements | |
this.achievements = [ | |
{ id: 1, name: 'First Course', icon: 'fas fa-graduation-cap' }, | |
{ id: 2, name: 'Quiz Master', icon: 'fas fa-trophy' }, | |
{ id: 3, name: '100 Hours', icon: 'fas fa-clock' }, | |
{ id: 4, name: 'Top Student', icon: 'fas fa-medal' } | |
]; | |
}, | |
loadMockData() { | |
this.courses = [ | |
{ | |
id: 1, | |
title: 'Complete Web Development Bootcamp', | |
description: 'Learn HTML, CSS, JavaScript, React, Node.js and more', | |
thumbnail: 'https://images.unsplash.com/photo-1517694712202-14dd9538aa97', | |
instructor: 'John Doe', | |
rating: 4.8, | |
students: 1234, | |
price: 89, | |
category: 'Web Development', | |
level: 'beginner', | |
totalHours: 40, | |
videoUrl: 'https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_1mb.mp4', | |
sections: [ | |
{ | |
id: 1, | |
title: 'Introduction', | |
lectures: [ | |
{ id: 1, title: 'Course Overview', duration: '5:30', completed: true }, | |
{ id: 2, title: 'Setting Up Environment', duration: '10:15', completed: false } | |
] | |
} | |
], | |
comments: [ | |
{ id: 1, user: 'Alice', text: 'Great course! Really helped me understand React.' }, | |
{ id: 2, user: 'Bob', text: 'The instructor explains concepts very clearly.' } | |
] | |
}, | |
{ | |
id: 2, | |
title: 'Machine Learning A-Z', | |
description: 'Master machine learning algorithms and techniques', | |
thumbnail: 'https://images.unsplash.com/photo-1555949963-aa79dcee981c', | |
instructor: 'Jane Smith', | |
rating: 4.9, | |
students: 892, | |
price: 129, | |
category: 'AI & Machine Learning', | |
level: 'advanced', | |
totalHours: 60 | |
}, | |
{ | |
id: 3, | |
title: 'iOS Development with Swift', | |
description: 'Build iOS apps from scratch using Swift', | |
thumbnail: 'https://images.unsplash.com/photo-1555774698-0b77e916bb71', | |
instructor: 'Mike Johnson', | |
rating: 4.7, | |
students: 567, | |
price: 0, | |
category: 'Mobile Development', | |
level: 'intermediate', | |
totalHours: 35 | |
} | |
]; | |
this.featuredCourses = this.courses.slice(0, 3); | |
this.enrolledCourses = this.courses.slice(0, 2); | |
this.publishedCourses = this.courses.slice(0, 1); | |
this.totalStudents = 1234; | |
this.totalRevenue = 8940; | |
this.certificatesEarned = 3; | |
this.totalHours = 75; | |
}, | |
openModal(type) { | |
this.modalType = type; | |
this.showModal = true; | |
}, | |
closeModal() { | |
this.showModal = false; | |
this.modalType = ''; | |
}, | |
login() { | |
// Mock login | |
this.user = { | |
id: 1, | |
name: this.loginForm.email.split('@')[0], | |
email: this.loginForm.email, | |
role: 'student' | |
}; | |
localStorage.setItem('eduLoomUser', JSON.stringify(this.user)); | |
this.closeModal(); | |
this.showNotification = true; | |
this.notificationMessage = 'Successfully logged in!'; | |
this.notificationType = 'success'; | |
setTimeout(() => this.showNotification = false, 3000); | |
}, | |
register() { | |
// Mock registration | |
this.user = { | |
id: Date.now(), | |
name: this.registerForm.name, | |
email: this.registerForm.email, | |
role: this.registerForm.role | |
}; | |
localStorage.setItem('eduLoomUser', JSON.stringify(this.user)); | |
this.closeModal(); | |
this.showNotification = true; | |
this.notificationMessage = 'Account created successfully!'; | |
this.notificationType = 'success'; | |
setTimeout(() => this.showNotification = false, 3000); | |
}, | |
logout() { | |
this.user = null; | |
localStorage.removeItem('eduLoomUser'); | |
this.currentPage = 'home'; | |
this.profileDropdown = false; | |
}, | |
searchCourses() { | |
// Implement search functionality | |
if (this.searchQuery.length > 0) { | |
this.filteredCourses = this.courses.filter(course => | |
course.title.toLowerCase().includes(this.searchQuery.toLowerCase()) || | |
course.description.toLowerCase().includes(this.searchQuery.toLowerCase()) | |
); | |
} else { | |
this.filteredCourses = this.courses; | |
} | |
}, | |
filterByCategory(category) { | |
this.filteredCourses = this.courses.filter(course => course.category === category); | |
}, | |
resetFilters() { | |
this.filters = { | |
level: '', | |
price: '', | |
rating: '' | |
}; | |
this.filteredCourses = this.courses; | |
}, | |
viewCourse(course) { | |
this.selectedCourse = course; | |
this.currentPage = 'course-detail'; | |
}, | |
enrollCourse(course) { | |
this.enrolledCourses.push(course); | |
this.showNotification = true; | |
this.notificationMessage = `Successfully enrolled in ${course.title}!`; | |
this.notificationType = 'success'; | |
setTimeout(() => this.showNotification = false, 3000); | |
}, | |
isEnrolled(courseId) { | |
return this.enrolledCourses.some(course => course.id === courseId); | |
}, | |
getCourseProgress(courseId) { | |
// Mock progress calculation | |
return Math.floor(Math.random() * 100); | |
}, | |
toggleWishlist(course) { | |
const index = this.wishlist.findIndex(c => c.id === course.id); | |
if (index > -1) { | |
this.wishlist.splice(index, 1); | |
} else { | |
this.wishlist.push(course); | |
} | |
}, | |
isInWishlist(courseId) { | |
return this.wishlist.some(course => course.id === courseId); | |
}, | |
createCourse() { | |
const course = { | |
id: Date.now(), | |
title: this.newCourse.title, | |
description: this.newCourse.description, | |
category: this.newCourse.category, | |
price: this.newCourse.price, | |
instructor: this.user.name, | |
thumbnail: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3', | |
rating: 0, | |
students: 0 | |
}; | |
this.publishedCourses.push(course); | |
this.newCourse = { title: '', description: '', category: '', price: 0 }; | |
this.showNotification = true; | |
this.notificationMessage = 'Course created successfully!'; | |
setTimeout(() => this.showNotification = false, 3000); | |
}, | |
updateProfile() { | |
this.user.name = `${this.userProfile.firstName} ${this.userProfile.lastName}`; | |
this.showNotification = true; | |
this.notificationMessage = 'Profile updated successfully!'; | |
setTimeout(() => this.showNotification = false, 3000); | |
}, | |
processPayment() { | |
// Mock payment processing | |
this.closeModal(); | |
this.enrollCourse(this.selectedCourse); | |
}, | |
sendChatMessage() { | |
if (this.chatInput.trim()) { | |
this.chatMessages.push({ | |
id: Date.now(), | |
type: 'user', | |
text: this.chatInput | |
}); | |
// Mock AI response | |
setTimeout(() => { | |
this.chatMessages.push({ | |
id: Date.now() + 1, | |
type: 'ai', | |
text: `I understand you're asking about "${this.chatInput}". How can I help you with this topic?` | |
}); | |
}, 1000); | |
this.chatInput = ''; | |
} | |
}, | |
toggleNotifications() { | |
// Toggle notifications panel | |
console.log('Notifications toggled'); | |
}, | |
postComment() { | |
if (this.newComment.trim() && this.selectedCourse) { | |
const comment = { | |
id: Date.now(), | |
user: this.user.name, | |
text: this.newComment | |
}; | |
this.selectedCourse.comments.push(comment); | |
this.newComment = ''; | |
} | |
} | |
} | |
} | |
</script> | |
</body> | |
</html> |