Spaces:
Running
Running
| // ShortForge AI – Landing page JS | |
| document.getElementById('demoBtn').addEventListener('click', () => { | |
| document.getElementById('demoSection').classList.toggle('hidden'); | |
| }); | |
| async loadTemplates() { | |
| this.showLoading(true); | |
| // Simulate API call with generated images | |
| const categories = ['nature', 'technology', 'people', 'abstract', 'minimal']; | |
| const sizes = ['200x200', '320x240', '640x360', '1024x576', '1200x630']; | |
| const templates = []; | |
| for (let i = 0; i < 20; i++) { | |
| const category = categories[Math.floor(Math.random() * categories.length)]; | |
| const size = sizes[Math.floor(Math.random() * sizes.length)]; | |
| const seed = Math.floor(Math.random() * 999) + 1; | |
| templates.push({ | |
| id: i + 1, | |
| title: `${category.charAt(0).toUpperCase() + category.slice(1)} Template ${i + 1}`, | |
| category: category, | |
| size: size, | |
| image: `http://static.photos/${category}/${size}/${seed}`, | |
| downloads: Math.floor(Math.random() * 1000), | |
| likes: Math.floor(Math.random() * 500), | |
| tags: [category, 'template', 'ai-generated'] | |
| }); | |
| } | |
| this.templates = templates; | |
| this.renderTemplates(); | |
| this.showLoading(false); | |
| } | |
| renderTemplates() { | |
| const container = document.getElementById('templatesContainer'); | |
| const filteredTemplates = this.filterTemplates(); | |
| container.innerHTML = filteredTemplates.map(template => ` | |
| <div class="template-card bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden cursor-pointer" data-id="${template.id}"> | |
| <div class="relative"> | |
| <img src="${template.image}" alt="${template.title}" class="w-full h-48 object-cover"> | |
| <div class="absolute top-2 right-2 flex gap-2"> | |
| <span class="bg-black bg-opacity-50 text-white px-2 py-1 rounded text-xs"> | |
| ${template.size} | |
| </span> | |
| <button class="like-btn bg-white bg-opacity-80 hover:bg-opacity-100 rounded-full p-1 transition-all" data-id="${template.id}"> | |
| <i data-feather="heart" class="w-4 h-4 text-gray-600"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="p-4"> | |
| <h3 class="font-semibold text-gray-800 dark:text-white mb-2">${template.title}</h3> | |
| <div class="flex items-center justify-between text-sm text-gray-600 dark:text-gray-400"> | |
| <span class="flex items-center"> | |
| <i data-feather="download" class="w-4 h-4 mr-1"></i> | |
| ${template.downloads} | |
| </span> | |
| <span class="flex items-center"> | |
| <i data-feather="heart" class="w-4 h-4 mr-1"></i> | |
| ${template.likes} | |
| </span> | |
| </div> | |
| <div class="mt-3 flex flex-wrap gap-1"> | |
| ${template.tags.map(tag => ` | |
| <span class="bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 px-2 py-1 rounded text-xs"> | |
| ${tag} | |
| </span> | |
| `).join('')} | |
| </div> | |
| </div> | |
| </div> | |
| `).join(''); | |
| this.attachCardEvents(); | |
| feather.replace(); | |
| } | |
| filterTemplates() { | |
| return this.templates.filter(template => { | |
| const categoryMatch = !this.currentCategory || template.category === this.currentCategory; | |
| const sizeMatch = !this.currentSize || template.size === this.currentSize; | |
| return categoryMatch && sizeMatch; | |
| }); | |
| } | |
| attachCardEvents() { | |
| document.querySelectorAll('.template-card').forEach(card => { | |
| card.addEventListener('click', (e) => { | |
| if (!e.target.closest('.like-btn')) { | |
| const templateId = card.dataset.id; | |
| this.openTemplateModal(templateId); | |
| } | |
| }); | |
| }); | |
| document.querySelectorAll('.like-btn').forEach(btn => { | |
| btn.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| const templateId = btn.dataset.id; | |
| this.toggleLike(templateId); | |
| }); | |
| }); | |
| } | |
| openTemplateModal(templateId) { | |
| const template = this.templates.find(t => t.id == templateId); | |
| if (!template) return; | |
| const modal = document.createElement('div'); | |
| modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4'; | |
| modal.innerHTML = ` | |
| <div class="bg-white dark:bg-gray-800 rounded-lg max-w-4xl w-full max-h-full overflow-auto"> | |
| <div class="relative"> | |
| <button class="absolute top-4 right-4 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 z-10"> | |
| <i data-feather="x" class="w-6 h-6"></i> | |
| </button> | |
| <img src="${template.image}" alt="${template.title}" class="w-full h-96 object-cover rounded-t-lg"> | |
| </div> | |
| <div class="p-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 dark:text-white mb-4">${template.title}</h2> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6"> | |
| <div class="text-center"> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">Category</p> | |
| <p class="font-semibold text-gray-800 dark:text-white">${template.category}</p> | |
| </div> | |
| <div class="text-center"> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">Size</p> | |
| <p class="font-semibold text-gray-800 dark:text-white">${template.size}</p> | |
| </div> | |
| <div class="text-center"> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">Downloads</p> | |
| <p class="font-semibold text-gray-800 dark:text-white">${template.downloads}</p> | |
| </div> | |
| <div class="text-center"> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">Likes</p> | |
| <p class="font-semibold text-gray-800 dark:text-white">${template.likes}</p> | |
| </div> | |
| </div> | |
| <div class="flex gap-4"> | |
| <button class="flex-1 bg-blue-500 hover:bg-blue-600 text-white font-semibold py-3 rounded-lg transition-colors"> | |
| <i data-feather="download" class="inline w-5 h-5 mr-2"></i>Download | |
| </button> | |
| <button class="flex-1 bg-purple-500 hover:bg-purple-600 text-white font-semibold py-3 rounded-lg transition-colors"> | |
| <i data-feather="heart" class="inline w-5 h-5 mr-2"></i>Like | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| document.body.appendChild(modal); | |
| modal.querySelector('button').addEventListener('click', () => { | |
| document.body.removeChild(modal); | |
| }); | |
| modal.addEventListener('click', (e) => { | |
| if (e.target === modal) { | |
| document.body.removeChild(modal); | |
| } | |
| }); | |
| feather.replace(); | |
| } | |
| toggleLike(templateId) { | |
| const template = this.templates.find(t => t.id == templateId); | |
| if (template) { | |
| template.likes += 1; | |
| this.renderTemplates(); | |
| } | |
| } | |
| setupEventListeners() { | |
| document.getElementById('gridView').addEventListener('click', () => { | |
| this.currentView = 'grid'; | |
| document.getElementById('gridView').className = 'px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors'; | |
| document.getElementById('listView').className = 'px-6 py-3 bg-gray-300 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-400 dark:hover:bg-gray-600 transition-colors'; | |
| }); | |
| document.getElementById('listView').addEventListener('click', () => { | |
| this.currentView = 'list'; | |
| document.getElementById('listView').className = 'px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors'; | |
| document.getElementById('gridView').className = 'px-6 py-3 bg-gray-300 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-400 dark:hover:bg-gray-600 transition-colors'; | |
| }); | |
| document.getElementById('categoryFilter').addEventListener('change', (e) => { | |
| this.currentCategory = e.target.value; | |
| this.renderTemplates(); | |
| }); | |
| document.getElementById('sizeFilter').addEventListener('change', (e) => { | |
| this.currentSize = e.target.value; | |
| this.renderTemplates(); | |
| }); | |
| } | |
| setupThemeToggle() { | |
| const themeToggle = document.createElement('button'); | |
| themeToggle.id = 'themeToggle'; | |
| themeToggle.className = 'fixed bottom-4 right-4 bg-gray-800 dark:bg-gray-200 text-white dark:text-gray-800 p-3 rounded-full shadow-lg hover:shadow-xl transition-all'; | |
| themeToggle.innerHTML = '<i data-feather="sun" class="w-5 h-5"></i>'; | |
| document.body.appendChild(themeToggle); | |
| themeToggle.addEventListener('click', () => { | |
| document.documentElement.classList.toggle('dark'); | |
| const isDark = document.documentElement.classList.contains('dark'); | |
| themeToggle.innerHTML = isDark ? | |
| '<i data-feather="sun" class="w-5 h-5"></i>' : | |
| '<i data-feather="moon" class="w-5 h-5"></i>'; | |
| feather.replace(); | |
| }); | |
| } | |
| showLoading(show) { | |
| const spinner = document.getElementById('loadingSpinner'); | |
| spinner.classList.toggle('hidden', !show); | |
| } | |
| } | |
| // Initialize the app | |
| document.addEventListener('DOMContentLoaded', () => { | |
| new TemplateManager(); | |
| }); |