Spaces:
Running
Running
| // Toggle sidebar collapse | |
| function toggleSidebar() { | |
| const sidebar = document.querySelector('.sidebar'); | |
| sidebar.classList.toggle('collapsed'); | |
| // Save state to localStorage | |
| const isCollapsed = sidebar.classList.contains('collapsed'); | |
| localStorage.setItem('sidebarCollapsed', isCollapsed); | |
| } | |
| // Initialize sidebar state from localStorage | |
| function initSidebar() { | |
| const sidebar = document.querySelector('.sidebar'); | |
| const isCollapsed = localStorage.getItem('sidebarCollapsed') === 'true'; | |
| if (isCollapsed) { | |
| sidebar.classList.add('collapsed'); | |
| } | |
| } | |
| // Initialize tooltips | |
| function initTooltips() { | |
| const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); | |
| tooltipTriggerList.map(function (tooltipTriggerEl) { | |
| return new bootstrap.Tooltip(tooltipTriggerEl); | |
| }); | |
| } | |
| // Enhanced filter function with debounce | |
| function debounce(func, timeout = 300) { | |
| let timer; | |
| return (...args) => { | |
| clearTimeout(timer); | |
| timer = setTimeout(() => { func.apply(this, args); }, timeout); | |
| }; | |
| } | |
| const filterResources = debounce(function() { | |
| const searchTerm = document.getElementById('search').value.toLowerCase(); | |
| const categoryFilter = document.getElementById('category').value; | |
| const sortOption = document.getElementById('sort').value; | |
| const slides = document.querySelectorAll('#slides-container .card'); | |
| const slidesArray = Array.from(slides); | |
| // Filter | |
| slides.forEach(slide => { | |
| const title = slide.querySelector('h3').textContent.toLowerCase(); | |
| const category = slide.querySelector('span').textContent; | |
| const matchesSearch = title.includes(searchTerm); | |
| const matchesCategory = !categoryFilter || category === categoryFilter; | |
| if (matchesSearch && matchesCategory) { | |
| slide.style.display = 'block'; | |
| } else { | |
| slide.style.display = 'none'; | |
| } | |
| }); | |
| // Sort | |
| slidesArray.sort((a, b) => { | |
| const titleA = a.querySelector('h3').textContent.toLowerCase(); | |
| const titleB = b.querySelector('h3').textContent.toLowerCase(); | |
| const dateA = a.querySelector('.text-sm.text-gray-500').textContent; | |
| const dateB = b.querySelector('.text-sm.text-gray-500').textContent; | |
| switch(sortOption) { | |
| case 'name': | |
| return titleA.localeCompare(titleB); | |
| case 'oldest': | |
| return new Date(dateA) - new Date(dateB); | |
| case 'recent': | |
| default: | |
| return new Date(dateB) - new Date(dateA); | |
| } | |
| }); | |
| // Re-append sorted slides | |
| const container = document.getElementById('slides-container'); | |
| container.innerHTML = ''; | |
| slidesArray.forEach(slide => container.appendChild(slide)); | |
| } | |
| // Reset filters function | |
| function resetFilters() { | |
| document.getElementById('search').value = ''; | |
| document.getElementById('category').value = ''; | |
| document.getElementById('sort').value = 'recent'; | |
| filterSlides(); | |
| } | |
| // Add hover effects to all cards | |
| function initCardEffects() { | |
| const cards = document.querySelectorAll('.card-hover'); | |
| cards.forEach(card => { | |
| card.addEventListener('mousemove', (e) => { | |
| const rect = card.getBoundingClientRect(); | |
| const x = e.clientX - rect.left; | |
| const y = e.clientY - rect.top; | |
| card.style.setProperty('--mouse-x', `${x}px`); | |
| card.style.setProperty('--mouse-y', `${y}px`); | |
| // Parallax effect for child elements | |
| const tiltX = (rect.width / 2 - x) / 20; | |
| const tiltY = (rect.height / 2 - y) / 20; | |
| card.style.transform = `perspective(1000px) rotateX(${tiltY}deg) rotateY(${-tiltX}deg)`; | |
| }); | |
| card.addEventListener('mouseleave', () => { | |
| card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)'; | |
| }); | |
| }); | |
| } | |
| // Initialize glow effects | |
| function initGlowEffects() { | |
| // Auto add glow effect to all buttons with class 'glow' | |
| document.querySelectorAll('.btn-primary').forEach(btn => { | |
| const glow = document.createElement('glow-effect'); | |
| glow.setAttribute('r', '139'); | |
| glow.setAttribute('g', '92'); | |
| glow.setAttribute('b', '246'); | |
| btn.appendChild(glow); | |
| }); | |
| } | |
| // Dark mode toggle | |
| function initDarkMode() { | |
| const darkModeToggle = document.getElementById('dark-mode-toggle'); | |
| if (darkModeToggle) { | |
| darkModeToggle.addEventListener('click', () => { | |
| document.documentElement.classList.toggle('dark'); | |
| localStorage.setItem('darkMode', document.documentElement.classList.contains('dark')); | |
| }); | |
| // Initialize from localStorage | |
| if (localStorage.getItem('darkMode') === 'true') { | |
| document.documentElement.classList.add('dark'); | |
| } | |
| } | |
| } | |
| // Smooth scroll animation | |
| function smoothScroll(target, duration) { | |
| const targetElement = document.querySelector(target); | |
| const targetPosition = targetElement.getBoundingClientRect().top; | |
| const startPosition = window.pageYOffset; | |
| const distance = targetPosition; | |
| let startTime = null; | |
| function animation(currentTime) { | |
| if (startTime === null) startTime = currentTime; | |
| const timeElapsed = currentTime - startTime; | |
| const run = ease(timeElapsed, startPosition, distance, duration); | |
| window.scrollTo(0, run); | |
| if (timeElapsed < duration) requestAnimationFrame(animation); | |
| } | |
| function ease(t, b, c, d) { | |
| t /= d / 2; | |
| if (t < 1) return c / 2 * t * t + b; | |
| t--; | |
| return -c / 2 * (t * (t - 2) - 1) + b; | |
| } | |
| requestAnimationFrame(animation); | |
| } | |
| // Initialize the app when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initSidebar(); | |
| initCardEffects(); | |
| initGlowEffects(); | |
| initDarkMode(); | |
| // Add event listeners | |
| const sidebarToggle = document.querySelector('custom-sidebar')?.shadowRoot?.querySelector('.sidebar-toggle'); | |
| if (sidebarToggle) { | |
| sidebarToggle.addEventListener('click', toggleSidebar); | |
| } | |
| // Initialize tooltips if Bootstrap is loaded | |
| if (typeof bootstrap !== 'undefined') { | |
| initTooltips(); | |
| } | |
| // Add filter event listeners if on slides, blocks, assessments or marketplace page | |
| if (document.getElementById('search') && !document.querySelector('.marketplace-search')) { | |
| const searchInput = document.getElementById('search'); | |
| const categorySelect = document.getElementById('category'); | |
| const sortSelect = document.getElementById('sort'); | |
| const resetBtn = document.getElementById('reset-filters'); | |
| if (searchInput) searchInput.addEventListener('input', filterSlides); | |
| if (categorySelect) categorySelect.addEventListener('change', filterSlides); | |
| if (sortSelect) sortSelect.addEventListener('change', filterSlides); | |
| if (resetBtn) resetBtn.addEventListener('click', resetFilters); | |
| } | |
| }); | |
| // AI Assistant functionality | |
| function initAIAssistant() { | |
| const chatInput = document.querySelector('.ai-assistant input[type="text"]'); | |
| const sendBtn = document.querySelector('.ai-assistant button'); | |
| if (chatInput && sendBtn) { | |
| sendBtn.addEventListener('click', function() { | |
| const message = chatInput.value.trim(); | |
| if (message) { | |
| addUserMessage(message); | |
| chatInput.value = ''; | |
| // Simulate AI response after a short delay | |
| setTimeout(() => { | |
| addAIMessage("I'm your AI assistant. In a real implementation, this would be a response from the AI service."); | |
| }, 1000); | |
| } | |
| }); | |
| chatInput.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') { | |
| sendBtn.click(); | |
| } | |
| }); | |
| } | |
| } | |
| function addUserMessage(message) { | |
| const chatContainer = document.getElementById('chat-messages'); | |
| if (chatContainer) { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = 'flex items-start justify-end'; | |
| messageDiv.innerHTML = ` | |
| <div class="bg-indigo-600 text-white rounded-lg p-4 max-w-3xl"> | |
| <p>${message}</p> | |
| </div> | |
| <div class="h-8 w-8 rounded-full bg-indigo-600 flex items-center justify-center text-white ml-3 flex-shrink-0"> | |
| <i class="fas fa-user"></i> | |
| </div> | |
| `; | |
| chatContainer.appendChild(messageDiv); | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| } | |
| } | |
| function addAIMessage(message) { | |
| const chatContainer = document.getElementById('chat-messages'); | |
| if (chatContainer) { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = 'flex items-start'; | |
| messageDiv.innerHTML = ` | |
| <div class="h-8 w-8 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-600 mr-3 flex-shrink-0"> | |
| <i class="fas fa-robot"></i> | |
| </div> | |
| <div class="bg-indigo-50 rounded-lg p-4 max-w-3xl"> | |
| <p class="text-gray-800">${message}</p> | |
| </div> | |
| `; | |
| chatContainer.appendChild(messageDiv); | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| } | |
| } | |
| // Initialize the app when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initSidebar(); | |
| initAIAssistant(); | |
| // Responsive adjustments | |
| window.addEventListener('resize', function() { | |
| // Add any responsive adjustments here | |
| if (window.innerWidth < 768) { | |
| document.querySelector('.sidebar').classList.add('collapsed'); | |
| } | |
| }); |