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> |