Spaces:
Running
// Mobile Navigation Toggle
Browse filesconst hamburger = document.querySelector('.hamburger');
const navMenu = document.querySelector('.nav-menu');
hamburger.addEventListener('click', () => {
hamburger.classList.toggle('active');
navMenu.classList.toggle('active');
});
// Close mobile menu when clicking on a link
document.querySelectorAll('.nav-menu a').forEach(link => {
link.addEventListener('click', () => {
hamburger.classList.remove('active');
navMenu.classList.remove('active');
});
});
// Navbar scroll effect
window.addEventListener('scroll', () => {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 100) {
navbar.style.background = 'rgba(255, 255, 255, 0.98)';
navbar.style.boxShadow = '0 2px 20px rgba(0, 0, 0, 0.1)';
} else {
navbar.style.background = 'rgba(255, 255, 255, 0.95)';
navbar.style.boxShadow = 'none';
}
});
// Smooth scrolling for navigation links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Intersection Observer for fade-in animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Apply fade-in animation to elements
document.addEventListener('DOMContentLoaded', () => {
const animatedElements = document.querySelectorAll('.category-card, .prompt-card, .pricing-card, .feature-item');
const batchSize = 20; // Number of elements to observe at once
animatedElements.forEach((el, index) => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
if (index < batchSize) {
observer.observe(el);
}
});
function animateCounter(element, target, duration = 2000) {
let start = 0;
const startTime = performance.now();
function update(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
const value = Math.floor(progress * target);
element.textContent = formatNumber(progress === 1 ? target : value);
if (progress < 1) {
requestAnimationFrame(update);
}
}
requestAnimationFrame(update);
}
});
// Counter animation for hero stats
function animateCounter(element, target, duration = 2000) {
let start = 0;
const increment = target / (duration / 16);
const timer = setInterval(() => {
start += increment;
if (start >= target) {
element.textContent = formatNumber(target);
clearInterval(timer);
} else {
element.textContent = formatNumber(Math.floor(start));
}
}, 16);
}
function formatNumber(num) {
if (num >= 1000) {
return (num / 1000).toFixed(0) + 'K+';
}
return num + '+';
}
// Trigger counter animation when hero section is visible
const heroObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const statNumbers = document.querySelectorAll('.stat-number');
const targets = [500, 10000, 99];
statNumbers.forEach((stat, index) => {
if (targets[index]) {
animateCounter(stat, targets[index]);
}
});
heroObserver.unobserve(entry.target);
}
});
});
document.addEventListener('DOMContentLoaded', () => {
const heroSection = document.querySelector('.hero');
if (heroSection) {
heroObserver.observe(heroSection);
}
});
// Form handling
const contactForm = document.querySelector('.contact-form');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
// Get form data
const formData = new FormData(this);
const name = this.querySelector('input[type="text"]').value;
const email = this.querySelector('input[type="email"]').value;
const topic = this.querySelector('select').value;
const message = this.querySelector('textarea').value;
// Basic validation
if (!name || !email || !topic || !message) {
showNotification('Please fill in all fields', 'error');
return;
}
if (!isValidEmail(email)) {
showNotification('Please enter a valid email address', 'error');
return;
}
// Simulate form submission
showNotification('Message sent successfully! We\'ll get back to you soon.', 'success');
this.reset();
});
}
// Email validation
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// Notification system
function showNotification(message, type = 'info') {
// Remove existing notifications
const existingNotifications = document.querySelectorAll('.notification');
existingNotifications.forEach(notification => notification.remove());
// Create notification element
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.innerHTML = `
<div class="notification-content">
<span class="notification-icon">
${type === 'success' ? '✓' : type === 'error' ? '✗' : 'ℹ'}
</span>
<span class="notification-message">${message}</span>
<button class="notification-close">×</button>
</div>
`;
// Add styles
notification.style.cssText = `
position: fixed;
top: 100px;
right: 20px;
z-index: 10000;
max-width: 400px;
background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#6366f1'};
color: white;
padding: 1rem;
border-radius: 0.5rem;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
transform: translateX(100%);
transition: transform 0.3s ease;
`;
// Add notification to page
document.body.appendChild(notification);
// Add close button event listener
notification.querySelector('.notification-close').addEventListener('click', function() {
notification.style.transform = 'translateX(100%)';
setTimeout(() => notification.remove(), 300);
});
// Trigger animation
setTimeout(() => {
notification.style.transform = 'translateX(0)';
}, 100);
// Auto remove after 5 seconds
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
setTimeout(() => notification.remove(), 300);
}, 5000);
}
// Buy button functionality
document.addEventListener('DOMContentLoaded', () => {
const buyButtons = document.querySelectorAll('.btn-buy');
buyButtons.forEach(button => {
button.addEventListener('click', function() {
const promptCard = this.closest('.prompt-card');
const promptTitle = promptCard.querySelector('h3').textContent;
const promptPrice = promptCard.querySelector('.prompt-price').textContent;
// Simulate purchase process
this.textContent = 'Processing...';
this.disabled = true;
setTimeout(() => {
showNotification(`Added "${promptTitle}" to cart for ${promptPrice}`, 'success');
this.textContent = 'Add to Cart';
this.disabled = false;
}, 1500);
});
});
});
// Pricing button functionality
document.addEventListener('DOMContentLoaded', () => {
const pricingButtons = document.querySelectorAll('.btn-pricing');
pricingButtons.forEach(button => {
button.addEventListener('click', function() {
const pricingCard = this.closest('.pricing-card');
const planName = pricingCard.querySelector('h3').textContent;
if (this.textContent === 'Contact Sales') {
// Scroll to contact section
document.querySelector('#contact').scrollIntoView({
behavior: 'smooth'
});
showNotification('Please fill out the contact form for Enterprise pricing', 'info');
} else {
// Simulate subscription process
this.textContent = 'Processing...';
this.disabled = true;
setTimeout(() => {
showNotification(`Redirecting to checkout for ${planName} plan...`, 'success');
this.textContent = 'Get Started';
this.disabled = false;
}, 1500);
}
});
});
});
// Category explore button functionality
document.addEventListener('DOMContentLoaded', () => {
const categoryButtons = document.querySelectorAll('.category-btn');
categoryButtons.forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
const categoryCard = this.closest('.category-card');
const categoryTitle = categoryCard.querySelector('h3').textContent;
showNotification(`Browsing ${categoryTitle}...`, 'info');
// Simulate loading category page
setTimeout(() => {
showNotification(`Found prompts in ${categoryTitle} category`, 'success');
}, 1000);
});
});
});
// Search functionality (if search box is added)
function initializeSearch() {
const searchInput =
|
@@ -1,5 +1,5 @@
|
|
| 1 |
|
| 2 |
-
//
|
| 3 |
const communityPosts = [
|
| 4 |
{
|
| 5 |
id: 1,
|
|
@@ -29,8 +29,7 @@ const communityPosts = [
|
|
| 29 |
timestamp: '1 day ago'
|
| 30 |
}
|
| 31 |
];
|
| 32 |
-
|
| 33 |
-
// Render community feed
|
| 34 |
function renderCommunityFeed() {
|
| 35 |
const feedContainer = document.getElementById('community-feed');
|
| 36 |
feedContainer.innerHTML = '';
|
|
@@ -68,13 +67,19 @@ function renderCommunityFeed() {
|
|
| 68 |
});
|
| 69 |
feather.replace();
|
| 70 |
}
|
| 71 |
-
|
| 72 |
document.addEventListener('DOMContentLoaded', function() {
|
| 73 |
-
// Initialize
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
const tabPanels = document.querySelectorAll('[role="tabpanel"]');
|
| 79 |
|
| 80 |
tabs.forEach(tab => {
|
|
|
|
| 1 |
|
| 2 |
+
// Enhanced community feed data with loading states
|
| 3 |
const communityPosts = [
|
| 4 |
{
|
| 5 |
id: 1,
|
|
|
|
| 29 |
timestamp: '1 day ago'
|
| 30 |
}
|
| 31 |
];
|
| 32 |
+
// Enhanced render community feed with error handling
|
|
|
|
| 33 |
function renderCommunityFeed() {
|
| 34 |
const feedContainer = document.getElementById('community-feed');
|
| 35 |
feedContainer.innerHTML = '';
|
|
|
|
| 67 |
});
|
| 68 |
feather.replace();
|
| 69 |
}
|
|
|
|
| 70 |
document.addEventListener('DOMContentLoaded', function() {
|
| 71 |
+
// Initialize accessibility features
|
| 72 |
+
initAccessibility();
|
| 73 |
+
// Initialize community feed with loading state
|
| 74 |
+
document.getElementById('community-feed').innerHTML = `
|
| 75 |
+
<div class="col-span-full text-center py-12">
|
| 76 |
+
<div class="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-primary-pink"></div>
|
| 77 |
+
<p class="mt-2 text-gray-400">Loading community creations...</p>
|
| 78 |
+
</div>
|
| 79 |
+
`;
|
| 80 |
+
renderCommunityFeed();
|
| 81 |
+
// Enhanced tab functionality with keyboard navigation
|
| 82 |
+
const tabs = document.querySelectorAll('[role="tab"]');
|
| 83 |
const tabPanels = document.querySelectorAll('[role="tabpanel"]');
|
| 84 |
|
| 85 |
tabs.forEach(tab => {
|