| | |
| | const products = [ |
| | { |
| | id: 1, |
| | name: "iPhone 15 Pro Max", |
| | category: "phones", |
| | price: 1199, |
| | originalPrice: 1299, |
| | image: "https://images.unsplash.com/photo-1696446701796-da61225697cc?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.9, |
| | reviews: 2341, |
| | badge: "Best Seller", |
| | description: "Titanium design. A17 Pro chip. Action button. 48MP Main camera. 5x Telephoto.", |
| | specs: ["256GB Storage", "A17 Pro Chip", "48MP Camera", "5x Zoom"] |
| | }, |
| | { |
| | id: 2, |
| | name: "MacBook Pro 16", |
| | category: "laptops", |
| | price: 2499, |
| | originalPrice: 2699, |
| | image: "https://images.unsplash.com/photo-1517336714731-489689fd1ca8?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.8, |
| | reviews: 1856, |
| | badge: "New", |
| | description: "M3 Max chip. 16-inch Liquid Retina XDR display. Up to 22 hours battery life.", |
| | specs: ["M3 Max", "36GB RAM", "1TB SSD", "16-inch Display"] |
| | }, |
| | { |
| | id: 3, |
| | name: "Sony WH-1000XM5", |
| | category: "audio", |
| | price: 399, |
| | originalPrice: 449, |
| | image: "https://images.unsplash.com/photo-1618366712010-f4ae9c647dcb?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.7, |
| | reviews: 3422, |
| | badge: "Popular", |
| | description: "Industry-leading noise cancellation. 30-hour battery life. Crystal clear hands-free calling.", |
| | specs: ["Noise Cancelling", "30h Battery", "Multipoint", "LDAC"] |
| | }, |
| | { |
| | id: 4, |
| | name: "PlayStation 5", |
| | category: "gaming", |
| | price: 499, |
| | originalPrice: 549, |
| | image: "https://images.unsplash.com/photo-1606813907291-d86efa9b94db?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.9, |
| | reviews: 5621, |
| | badge: "Hot", |
| | description: "Experience lightning-fast loading with an ultra-high-speed SSD and haptic feedback.", |
| | specs: ["4K Gaming", "Ray Tracing", "SSD", "DualSense"] |
| | }, |
| | { |
| | id: 5, |
| | name: "Apple Watch Ultra 2", |
| | category: "accessories", |
| | price: 799, |
| | originalPrice: 799, |
| | image: "https://images.unsplash.com/photo-1434493789847-2f02dc6ca35d?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.8, |
| | reviews: 1234, |
| | badge: null, |
| | description: "The most rugged and capable Apple Watch. 49mm titanium case. Precision GPS.", |
| | specs: ["49mm", "Titanium", "100m Water", "72h Battery"] |
| | }, |
| | { |
| | id: 6, |
| | name: "Samsung Galaxy S24 Ultra", |
| | category: "phones", |
| | price: 1299, |
| | originalPrice: 1399, |
| | image: "https://images.unsplash.com/photo-1610945265078-3858a0828671?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.7, |
| | reviews: 1890, |
| | badge: "New", |
| | description: "Galaxy AI is here. 200MP camera. S Pen built-in. Titanium frame.", |
| | specs: ["200MP Camera", "S Pen", "Galaxy AI", "Titanium"] |
| | }, |
| | { |
| | id: 7, |
| | name: "Dell XPS 15", |
| | category: "laptops", |
| | price: 1899, |
| | originalPrice: 2099, |
| | image: "https://images.unsplash.com/photo-1593642632823-8f78536788c6?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.6, |
| | reviews: 876, |
| | badge: null, |
| | description: "Stunning OLED display. 13th Gen Intel Core. NVIDIA 40-series graphics.", |
| | specs: ["OLED Touch", "i9-13900H", "RTX 4070", "32GB RAM"] |
| | }, |
| | { |
| | id: 8, |
| | name: "AirPods Pro 2", |
| | category: "audio", |
| | price: 249, |
| | originalPrice: 299, |
| | image: "https://images.unsplash.com/photo-1603351154351-5cfb3d04ef32?w=500&auto=format&fit=crop&q=80", |
| | rating: 4.8, |
| | reviews: 8934, |
| | badge: "Best Seller", |
| | description: "Active Noise Cancellation with Adaptive Audio. Personalized Spatial Audio.", |
| | specs: ["ANC", "Spatial Audio", "6h Battery", "MagSafe"] |
| | } |
| | ]; |
| |
|
| | |
| | let cart = []; |
| | let currentCategory = 'all'; |
| | let searchQuery = ''; |
| |
|
| | |
| | const productsGrid = document.getElementById('products-grid'); |
| | const cartSidebar = document.getElementById('cart-sidebar'); |
| | const cartOverlay = document.getElementById('cart-overlay'); |
| | const cartItems = document.getElementById('cart-items'); |
| | const cartBadge = document.getElementById('cart-badge'); |
| | const cartSubtotal = document.getElementById('cart-subtotal'); |
| | const cartTotal = document.getElementById('cart-total'); |
| | const mobileMenu = document.getElementById('mobile-menu'); |
| | const searchOverlay = document.getElementById('search-overlay'); |
| | const searchInput = document.getElementById('search-input'); |
| |
|
| | |
| | document.addEventListener('DOMContentLoaded', () => { |
| | renderProducts(); |
| | lucide.createIcons(); |
| | }); |
| |
|
| | |
| | function renderProducts() { |
| | let filtered = products; |
| | |
| | |
| | if (currentCategory !== 'all') { |
| | filtered = filtered.filter(p => p.category === currentCategory); |
| | } |
| | |
| | |
| | if (searchQuery) { |
| | filtered = filtered.filter(p => |
| | p.name.toLowerCase().includes(searchQuery.toLowerCase()) || |
| | p.description.toLowerCase().includes(searchQuery.toLowerCase()) |
| | ); |
| | } |
| | |
| | productsGrid.innerHTML = filtered.map((product, index) => ` |
| | <div class="product-card stagger-item bg-slate-800 rounded-2xl border border-slate-700 overflow-hidden group" style="animation-delay: ${index * 0.1}s"> |
| | <div class="relative img-zoom aspect-square bg-slate-900"> |
| | <img src="${product.image}" alt="${product.name}" class="w-full h-full object-cover"> |
| | ${product.badge ? ` |
| | <div class="absolute top-4 left-4 px-3 py-1 bg-blue-600 text-white text-xs font-bold rounded-full"> |
| | ${product.badge} |
| | </div> |
| | ` : ''} |
| | <button onclick="openProductModal(${product.id})" class="quick-view absolute bottom-4 right-4 p-3 bg-white/90 hover:bg-white text-slate-900 rounded-full shadow-lg backdrop-blur-sm"> |
| | <i data-lucide="eye" class="w-5 h-5"></i> |
| | </button> |
| | </div> |
| | <div class="p-5"> |
| | <div class="flex items-center justify-between mb-2"> |
| | <span class="text-xs font-medium text-blue-400 uppercase tracking-wider">${product.category}</span> |
| | <div class="flex items-center gap-1 text-sm"> |
| | <i data-lucide="star" class="w-4 h-4 text-yellow-500 fill-yellow-500"></i> |
| | <span class="text-slate-300">${product.rating}</span> |
| | <span class="text-slate-500">(${product.reviews})</span> |
| | </div> |
| | </div> |
| | <h3 class="font-semibold text-white mb-2 line-clamp-1">${product.name}</h3> |
| | <p class="text-sm text-slate-400 mb-4 line-clamp-2">${product.description}</p> |
| | <div class="flex items-center justify-between"> |
| | <div> |
| | <span class="text-xl font-bold text-white">$${product.price}</span> |
| | ${product.originalPrice > product.price ? ` |
| | <span class="text-sm text-slate-500 line-through ml-2">$${product.originalPrice}</span> |
| | ` : ''} |
| | </div> |
| | <button onclick="addToCart(${product.id})" class="p-3 bg-blue-600 hover:bg-blue-700 text-white rounded-xl transition-all transform hover:scale-105 active:scale-95"> |
| | <i data-lucide="plus" class="w-5 h-5"></i> |
| | </button> |
| | </div> |
| | </div> |
| | </div> |
| | `).join(''); |
| | |
| | lucide.createIcons(); |
| | } |
| |
|
| | |
| | function filterByCategory(category) { |
| | currentCategory = category; |
| | |
| | |
| | document.querySelectorAll('.category-btn').forEach(btn => { |
| | btn.classList.remove('active'); |
| | }); |
| | event.currentTarget.classList.add('active'); |
| | |
| | renderProducts(); |
| | } |
| |
|
| | |
| | function sortProducts() { |
| | const sortValue = document.getElementById('sort-select').value; |
| | |
| | switch(sortValue) { |
| | case 'price-low': |
| | products.sort((a, b) => a.price - b.price); |
| | break; |
| | case 'price-high': |
| | products.sort((a, b) => b.price - a.price); |
| | break; |
| | case 'newest': |
| | products.sort((a, b) => b.id - a.id); |
| | break; |
| | default: |
| | products.sort((a, b) => a.id - b.id); |
| | } |
| | |
| | renderProducts(); |
| | } |
| |
|
| | |
| | function toggleSearch() { |
| | searchOverlay.classList.toggle('hidden'); |
| | if (!searchOverlay.classList.contains('hidden')) { |
| | searchInput.focus(); |
| | } |
| | } |
| |
|
| | |
| | searchInput.addEventListener('input', (e) => { |
| | searchQuery = e.target.value; |
| | renderProducts(); |
| | }); |
| |
|
| | |
| | function toggleMobileMenu() { |
| | mobileMenu.classList.toggle('hidden'); |
| | } |
| |
|
| | |
| | function toggleCart() { |
| | cartSidebar.classList.toggle('translate-x-full'); |
| | cartOverlay.classList.toggle('hidden'); |
| | document.body.classList.toggle('overflow-hidden'); |
| | } |
| |
|
| | |
| | function addToCart(productId) { |
| | const product = products.find(p => p.id === productId); |
| | const existingItem = cart.find(item => item.id === productId); |
| | |
| | if (existingItem) { |
| | existingItem.quantity++; |
| | } else { |
| | cart.push({ ...product, quantity: 1 }); |
| | } |
| | |
| | updateCart(); |
| | showToast(`${product.name} added to cart!`); |
| | } |
| |
|
| | |
| | function removeFromCart(productId) { |
| | cart = cart.filter(item => item.id !== productId); |
| | updateCart(); |
| | } |
| |
|
| | |
| | function updateQuantity(productId, change) { |
| | const item = cart.find(item => item.id === productId); |
| | if (item) { |
| | item.quantity += change; |
| | if (item.quantity <= 0) { |
| | removeFromCart(productId); |
| | } else { |
| | updateCart(); |
| | } |
| | } |
| | } |
| |
|
| | |
| | function updateCart() { |
| | |
| | const totalItems = cart.reduce((sum, item) => sum + item.quantity, 0); |
| | cartBadge.textContent = totalItems; |
| | cartBadge.classList.toggle('hidden', totalItems === 0); |
| | |
| | |
| | if (cart.length === 0) { |
| | cartItems.innerHTML = ` |
| | <div class="text-center text-slate-500 py-12"> |
| | <i data-lucide="shopping-bag" class="w-12 h-12 mx-auto mb-4 opacity-50"></i> |
| | <p>Your cart is empty</p> |
| | </div> |
| | `; |
| | } else { |
| | cartItems.innerHTML = cart.map(item => ` |
| | <div class="cart-item flex gap-4 p-4 bg-slate-800 rounded-xl border border-slate-700"> |
| | <img src="${item.image}" alt="${item.name}" class="w-20 h-20 object-cover rounded-lg bg-slate-900"> |
| | <div class="flex-1 min-w-0"> |
| | <h4 class="font-medium text-white text-sm truncate">${item.name}</h4> |
| | <p class="text-blue-400 font-semibold mt-1">$${item.price}</p> |
| | <div class="flex items-center gap-3 mt-2"> |
| | <button onclick="updateQuantity(${item.id}, -1)" class="w-6 h-6 flex items-center justify-center bg-slate-700 hover:bg-slate-600 rounded text-white text-xs transition-colors">-</button> |
| | <span class="text-sm text-white w-4 text-center">${item.quantity}</span> |
| | <button onclick="updateQuantity(${item.id}, 1)" class="w-6 h-6 flex items-center justify-center bg-slate-700 hover:bg-slate-600 rounded text-white text-xs transition-colors">+</button> |
| | </div> |
| | </div> |
| | <button onclick="removeFromCart(${item.id})" class="p-2 hover:bg-slate-700 rounded-lg transition-colors self-start"> |
| | <i data-lucide="trash-2" class="w-4 h-4 text-slate-400"></i> |
| | </button> |
| | </div> |
| | `).join(''); |
| | } |
| | |
| | |
| | const subtotal = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0); |
| | cartSubtotal.textContent = `$${subtotal.toFixed(2)}`; |
| | cartTotal.textContent = `$${subtotal.toFixed(2)}`; |
| | |
| | lucide.createIcons(); |
| | } |
| |
|
| | |
| | function openProductModal(productId) { |
| | const product = products.find(p => p.id === productId); |
| | const modal = document.getElementById('product-modal'); |
| | const content = document.getElementById('modal-content'); |
| | |
| | content.innerHTML = ` |
| | <div class="img-zoom h-64 md:h-full bg-slate-950 rounded-t-3xl md:rounded-l-3xl md:rounded-tr-none overflow-hidden"> |
| | <img src="${product.image}" alt="${product.name}" class="w-full h-full object-cover"> |
| | </div> |
| | <div class="p-8 md:p-12 flex flex-col"> |
| | <div class="flex items-center gap-2 mb-4"> |
| | <span class="px-3 py-1 bg-blue-500/20 text-blue-400 text-xs font-bold rounded-full uppercase">${product.category}</span> |
| | ${product.badge ? `<span class="px-3 py-1 bg-purple-500/20 text-purple-400 text-xs font-bold rounded-full">${product.badge}</span>` : ''} |
| | </div> |
| | <h2 class="text-3xl font-bold text-white mb-4">${product.name}</h2> |
| | <div class="flex items-center gap-4 mb-6"> |
| | <div class="flex items-center gap-1"> |
| | <i data-lucide="star" class="w-5 h-5 text-yellow-500 fill-yellow-500"></i> |
| | <span class="text-white font-semibold">${product.rating}</span> |
| | </div> |
| | <span class="text-slate-500">${product.reviews} reviews</span> |
| | </div> |
| | <p class="text-slate-400 mb-6 leading-relaxed">${product.description}</p> |
| | |
| | <div class="grid grid-cols-2 gap-3 mb-8"> |
| | ${product.specs.map(spec => ` |
| | <div class="flex items-center gap-2 text-sm text-slate-300"> |
| | <i data-lucide="check-circle" class="w-4 h-4 text-blue-500"></i> |
| | ${spec} |
| | </div> |
| | `).join('')} |
| | </div> |
| | |
| | <div class="flex items-center justify-between pt-6 border-t border-slate-800 mt-auto"> |
| | <div> |
| | <span class="text-3xl font-bold text-white">$${product.price}</span> |
| | ${product.originalPrice > product.price ? ` |
| | <span class="text-lg text-slate-500 line-through ml-3">$${product.originalPrice}</span> |
| | ` : ''} |
| | </div> |
| | <button onclick="addToCart(${product.id}); closeProductModal();" class="px-8 py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-xl transition-all transform hover:scale-105 flex items-center gap-2"> |
| | <i data-lucide="shopping-cart" class="w-5 h-5"></i> |
| | Add to Cart |
| | </button> |
| | </div> |
| | </div> |
| | `; |
| | |
| | modal.classList.remove('hidden'); |
| | lucide.createIcons(); |
| | } |
| |
|
| | function closeProductModal() { |
| | document.getElementById('product-modal').classList.add('hidden'); |
| | } |
| |
|
| | |
| | function showToast(message) { |
| | const toast = document.getElementById('toast'); |
| | const toastMessage = document.getElementById('toast-message'); |
| | |
| | toastMessage.textContent = message; |
| | toast.classList.remove('translate-y-24'); |
| | |
| | setTimeout(() => { |
| | toast.classList.add('translate-y-24'); |
| | }, 3000); |
| | } |
| |
|
| | |
| | function checkout() { |
| | if (cart.length === 0) { |
| | showToast('Your cart is empty!'); |
| | return; |
| | } |
| | |
| | |
| | const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0); |
| | showToast(`Proceeding to checkout... Total: $${total.toFixed(2)}`); |
| | |
| | |
| | setTimeout(() => { |
| | cart = []; |
| | updateCart(); |
| | toggleCart(); |
| | showToast('Order placed successfully! 🎉'); |
| | }, 1500); |
| | } |
| |
|
| | |
| | function handleSubscribe(e) { |
| | e.preventDefault(); |
| | const email = e.target.querySelector('input').value; |
| | showToast(`Thanks for subscribing with ${email}!`); |
| | e.target.reset(); |
| | } |
| |
|
| | |
| | function scrollToProducts() { |
| | document.getElementById('products').scrollIntoView({ behavior: 'smooth' }); |
| | } |
| |
|
| | |
| | document.addEventListener('keydown', (e) => { |
| | if (e.key === 'Escape') { |
| | closeProductModal(); |
| | if (!cartSidebar.classList.contains('translate-x-full')) { |
| | toggleCart(); |
| | } |
| | if (!searchOverlay.classList.contains('hidden')) { |
| | toggleSearch(); |
| | } |
| | } |
| | }); |
| |
|
| | |
| | document.addEventListener('click', (e) => { |
| | if (!e.target.closest('nav') && !mobileMenu.classList.contains('hidden')) { |
| | mobileMenu.classList.add('hidden'); |
| | } |
| | }); |