NitinBot001's picture
add a 3d gift box roatating at background of hero section and this is for younger generation so make it trendy and facinating
40ee265 verified
// Main JavaScript for MysteryVault Unboxed
document.addEventListener('DOMContentLoaded', function() {
// Initialize all components
initPriceFilter();
initBoxesGrid();
initModalSystem();
initMobileMenu();
initNewsletterForm();
init3DGiftBox();
});
// Price Filter Functionality
function initPriceFilter() {
const priceRange = document.getElementById('priceRange');
const currentPrice = document.getElementById('currentPrice');
if (priceRange && currentPrice) {
// Update price display on input
priceRange.addEventListener('input', function() {
const price = `$${this.value}`;
currentPrice.textContent = price;
// Filter boxes based on price
filterBoxesByPrice(this.value);
});
}
}
// Box Data and Grid Management
const mysteryBoxes = [
{
id: 1,
name: "Starter Surprise",
price: 25,
category: "Electronics",
condition: "New",
image: "http://static.photos/technology/320x240/101",
description: "Perfect for beginners! Get 2-3 quality tech items worth up to $75.",
items: ["Wireless Earbuds", "Phone Case", "Cable Organizer"],
valueRange: "$50-75",
rating: 4.5
},
{
id: 2,
name: "Collector's Choice",
price: 75,
category: "Collectibles",
condition: "Like New",
image: "http://static.photos/vintage/320x240/102",
description: "Curated collectibles from popular franchises and limited editions.",
items: ["Action Figure", "Art Print", "Collectible Pin"],
valueRange: "$120-180",
rating: 4.8
},
{
id: 3,
name: "Premium Unbox",
price: 150,
category: "Luxury",
condition: "New",
image: "http://static.photos/luxury/320x240/103",
description: "High-end items including premium accessories and exclusive merchandise.",
items: ["Designer Watch", "Leather Wallet", "Sunglasses"],
valueRange: "$250-400",
rating: 4.9
},
{
id: 4,
name: "Gaming Mystery",
price: 45,
category: "Gaming",
condition: "Good",
image: "http://static.photos/gaming/320x240/104",
description: "Gamer's delight! Console accessories, games, and gaming merch.",
items: ["Controller", "Game Code", "Gaming Mousepad"],
valueRange: "$70-100",
rating: 4.3
},
{
id: 5,
name: "Fashion Vault",
price: 60,
category: "Fashion",
condition: "Like New",
image: "http://static.photos/fashion/320x240/105",
description: "Trendy fashion items and accessories from popular brands.",
items: ["T-Shirt", "Cap", "Socks"],
valueRange: "$90-130",
rating: 4.6
},
{
id: 6,
name: "Home & Living",
price: 35,
category: "Home",
condition: "New",
image: "http://static.photos/home/320x240/106",
description: "Cozy home essentials and decorative items to elevate your space.",
items: ["Throw Pillow", "Candle", "Kitchen Gadget"],
valueRange: "$55-80",
rating: 4.4
}
];
function initBoxesGrid() {
const boxesGrid = document.getElementById('boxesGrid');
if (!boxesGrid) return;
// Render all boxes initially
renderBoxes(mysteryBoxes, boxesGrid);
}
function renderBoxes(boxes, container) {
container.innerHTML = boxes.map(box => `
<div class="mystery-card bg-white rounded-2xl shadow-lg overflow-hidden hover-lift">
<div class="relative">
<img src="${box.image}" alt="${box.name}" class="w-full h-48 object-cover">
<div class="absolute top-4 right-4">
<span class="badge badge-${box.condition.toLowerCase().replace(' ', '-')}">
${box.condition}
</span>
</div>
<div class="p-6">
<div class="flex justify-between items-start mb-2">
<h3 class="text-xl font-bold text-gray-900">${box.name}</h3>
<span class="price-tag px-3 py-1 rounded-full text-sm font-bold">
$${box.price}
</span>
</div>
<p class="text-neutral mb-4 text-sm leading-relaxed">${box.description}</p>
<div class="flex items-center justify-between mb-4">
<span class="text-xs font-medium text-neutral bg-gray-100 px-2 py-1 rounded">
${box.category}
</span>
<div class="flex items-center">
<div class="flex text-accent">
${'β˜…'.repeat(Math.floor(box.rating))}${box.rating % 1 >= 0.5 ? 'Β½' : ''}${'β˜†'.repeat(5 - Math.ceil(box.rating))}
</div>
<span class="text-xs text-neutral ml-2">${box.rating}</span>
</div>
</div>
<div class="space-y-2">
<button class="quick-view-btn w-full bg-primary hover:bg-primary/90 text-white py-3 rounded-xl font-semibold transition-all duration-300" data-box-id="${box.id}">
Quick View
</button>
<button class="add-to-cart-btn w-full border-2 border-primary text-primary hover:bg-primary hover:text-white py-3 rounded-xl font-semibold transition-all duration-300">
Add to Cart
</button>
</div>
</div>
</div>
`).join('');
// Add event listeners to quick view buttons
document.querySelectorAll('.quick-view-btn').forEach(btn => {
btn.addEventListener('click', function() {
const boxId = parseInt(this.getAttribute('data-box-id'));
openQuickView(boxId);
});
});
}
function filterBoxesByPrice(maxPrice) {
const filteredBoxes = mysteryBoxes.filter(box => box.price <= maxPrice);
const boxesGrid = document.getElementById('boxesGrid');
if (boxesGrid) {
renderBoxes(filteredBoxes, boxesGrid);
}
// Modal System
function initModalSystem() {
const modal = document.getElementById('quickViewModal');
const closeBtn = document.getElementById('closeModal');
if (!modal || !closeBtn) return;
// Close modal on X button click
closeBtn.addEventListener('click', closeModal);
// Close modal on backdrop click
modal.addEventListener('click', function(e) {
if (e.target === modal) {
closeModal();
}
});
// Close modal on ESC key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
closeModal();
}
});
}
function openQuickView(boxId) {
const box = mysteryBoxes.find(b => b.id === boxId);
if (!box) return;
const modal = document.getElementById('quickViewModal');
const modalContent = document.getElementById('modalContent');
modalContent.innerHTML = `
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div>
<img src="${box.image}" alt="${box.name}" class="w-full rounded-2xl">
<div class="mt-4 flex items-center justify-between">
<span class="text-sm text-neutral">Estimated Value: <strong class="text-accent">${box.valueRange}</strong></span>
</div>
<div>
<h2 class="text-3xl font-bold mb-4">${box.name}</h2>
<p class="text-lg text-neutral mb-6 leading-relaxed">${box.description}</p>
<div class="mb-6">
<h4 class="font-bold mb-2">What's Inside:</h4>
<ul class="space-y-2">
${box.items.map(item => `
<li class="flex items-center text-neutral">
<i data-feather="check" class="w-4 h-4 mr-2 text-primary"></i>
${item}
</li>
`).join('')}
</ul>
</div>
<div class="space-y-4">
<div class="flex items-center justify-between">
<span class="text-lg font-semibold">Price:</span>
<span class="text-2xl font-bold text-primary">$${box.price}</span>
</div>
<div class="flex flex-col sm:flex-row gap-4 mt-6">
<button class="flex-1 bg-primary hover:bg-primary/90 text-white py-4 rounded-xl font-semibold text-lg transition-all duration-300 transform hover:scale-105">
Add to Cart
</button>
<button class="flex-1 border-2 border-primary text-primary hover:bg-primary hover:text-white py-4 rounded-xl font-semibold text-lg transition-all duration-300">
Save for Later
</button>
</div>
</div>
</div>
</div>
`;
modal.classList.remove('hidden');
feather.replace();
// TODO: Add analytics tracking for quick view opens
// analytics.track('quick_view_opened', { box_id: boxId });
}
function closeModal() {
const modal = document.getElementById('quickViewModal');
modal.classList.add('hidden');
}
// Mobile Menu Functionality
function initMobileMenu() {
const menuToggle = document.querySelector('[aria-label="Toggle menu"]');
const mobileMenu = document.getElementById('mobileMenu');
if (menuToggle && mobileMenu) {
menuToggle.addEventListener('click', function() {
mobileMenu.classList.toggle('open');
const icon = menuToggle.querySelector('i');
if (mobileMenu.classList.contains('open')) {
menuToggle.setAttribute('aria-expanded', 'true');
// TODO: Add focus trap for accessibility
} else {
menuToggle.setAttribute('aria-expanded', 'false');
}
// Update hamburger icon
feather.replace();
});
}
}
// Newsletter Form Handling
function initNewsletterForm() {
const newsletterForm = document.querySelector('form');
if (newsletterForm) {
newsletterForm.addEventListener('submit', function(e) {
e.preventDefault();
const email = this.querySelector('input[type="email"]').value;
// Simple validation
if (email && email.includes('@')) {
// TODO: Connect to newsletter API
// fetch('/api/newsletter', { method: 'POST', body: JSON.stringify({ email }) });
// Show success message
showNotification('Thanks for subscribing! Look out for exclusive offers.', 'success');
this.reset();
} else {
showNotification('Please enter a valid email address.', 'error');
}
});
}
}
// Notification System
function showNotification(message, type = 'info') {
// Create notification element
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 p-4 rounded-xl shadow-lg z-50 transform transition-all duration-300 ${
type === 'success' ? 'bg-primary text-white' :
type === 'error' ? 'bg-accent text-white' :
'bg-neutral text-white'
} fade-in`;
notification.textContent = message;
document.body.appendChild(notification);
// Remove after 5 seconds
setTimeout(() => {
notification.style.opacity = '0';
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
}, 300);
}, 5000);
}
// 3D Gift Box Animation
function init3DGiftBox() {
const giftBox = document.getElementById('giftBox3d');
if (!giftBox) return;
// Add sparkle particles
addSparkleParticles(giftBox);
// Add interactive hover effects
giftBox.addEventListener('mouseenter', function() {
this.style.animation = 'floatRotate 4s ease-in-out infinite, pulseGlow 2s ease-in-out infinite';
});
giftBox.addEventListener('mouseleave', function() {
this.style.animation = 'floatRotate 8s ease-in-out infinite';
});
}
function addSparkleParticles(container) {
const particleCount = 15;
for (let i = 0; i < particleCount; i++) {
const sparkle = document.createElement('div');
sparkle.className = 'sparkle';
// Random positions around the box
const angle = (i / particleCount) * Math.PI * 2;
const radius = Math.random() * 80 + 160;
sparkle.style.left = `calc(50% + ${Math.cos(angle) * radius}px`;
sparkle.style.top = `calc(50% + ${Math.sin(angle) * radius}px';
sparkle.style.animationDelay = `${Math.random() * 3}s`;
container.appendChild(sparkle);
}
}
// TODO: Connect to payment gateway (Stripe/PayPal)
// TODO: Fetch box inventory from API endpoint
// TODO: Handle newsletter signup POST request
// TODO: Add analytics tracking (Google Analytics/Plausible)
// TODO: Implement shopping cart functionality
// TODO: Add user authentication system
// TODO: Integrate with inventory management
// TODO: Add wishlist functionality
// TODO: Implement search functionality
// TODO: Add filter by category
// TODO: Add sorting options