// PalletPal Pro - Main JavaScript
// Product data
const products = [
{
id: 1,
name: "Standard 48x40\" New",
category: "new",
price: 12.99,
image: "http://static.photos/industry/640x480/1",
description: "Industry standard GMA pallet, heat-treated hardwood construction.",
specs: ["48\" x 40\" x 6\"", "2,500 lbs capacity", "ISPM-15 certified"]
},
{
id: 2,
name: "Heavy Duty Block Pallet",
category: "new",
price: 24.99,
image: "http://static.photos/industry/640x480/2",
description: "Four-way entry block pallet for heavy loads and rack storage.",
specs: ["48\" x 40\" x 6.5\"", "5,000 lbs capacity", "4-way entry"]
},
{
id: 3,
name: "Premium Used Grade A",
category: "used",
price: 6.99,
image: "http://static.photos/industry/640x480/3",
description: "Top-quality refurbished pallets, repaired to like-new condition.",
specs: ["48\" x 40\" x 6\"", "2,200 lbs capacity", "Heat treated"]
},
{
id: 4,
name: "Export/Heat Treated",
category: "export",
price: 15.99,
image: "http://static.photos/industry/640x480/4",
description: "ISPM-15 compliant pallets for international shipping.",
specs: ["48\" x 40\" x 6\"", "IPPC marked", "Global compliant"]
},
{
id: 5,
name: "Custom Size Pallet",
category: "custom",
price: 35.00,
image: "http://static.photos/craft/640x480/5",
description: "Built to your exact specifications and requirements.",
specs: ["Any size up to 96\"", "Custom capacity", "Your choice of wood"]
},
{
id: 6,
name: "Lightweight Economy",
category: "new",
price: 8.99,
image: "http://static.photos/industry/640x480/6",
description: "Cost-effective solution for light to medium loads.",
specs: ["48\" x 40\" x 5.5\"", "1,500 lbs capacity", "Softwood construction"]
}
];
// Testimonials data
const testimonials = [
{
id: 1,
name: "Robert Martinez",
company: "FastTrack Logistics",
role: "Operations Director",
image: "http://static.photos/people/200x200/101",
content: "PalletPal Pro has been our go-to supplier for 5 years. Their quality is consistent, delivery is always on time, and their team genuinely cares about our success.",
rating: 5
},
{
id: 2,
name: "Jennifer Walsh",
company: "Midwest Manufacturing",
role: "Supply Chain Manager",
image: "http://static.photos/people/200x200/102",
content: "The B2B program saved us 30% on pallet costs while eliminating stockouts. Their just-in-time delivery model transformed our warehouse operations.",
rating: 5
},
{
id: 3,
name: "David Kim",
company: "GreenGrocer Distributors",
role: "CEO",
image: "http://static.photos/people/200x200/103",
content: "As a company focused on sustainability, we love that PalletPal Pro shares our values. Their recycled pallet program aligns perfectly with our mission.",
rating: 5
}
];
// Pricing configuration
const pricing = {
standard: { base: 12.99, multiplier: 1 },
heavy: { base: 24.99, multiplier: 1 },
custom: { base: 35.00, multiplier: 1.2 },
used: { base: 6.99, multiplier: 1 },
export: { base: 15.99, multiplier: 1 }
};
const locationMultipliers = {
local: 1,
regional: 1.15,
national: 1.35
};
// DOM Ready
document.addEventListener('DOMContentLoaded', function() {
// Initialize Feather icons
if (typeof feather !== 'undefined') {
feather.replace();
}
// Load products on index page
loadFeaturedProducts();
// Load all products on products page
loadAllProducts();
// Load testimonials
loadTestimonials();
// Setup quote calculator
setupQuoteCalculator();
// Setup product filters
setupProductFilters();
// Setup forms
setupForms();
// Setup scroll animations
setupScrollAnimations();
});
// Load featured products (homepage)
function loadFeaturedProducts() {
const grid = document.getElementById('product-grid');
if (!grid) return;
const featuredProducts = products.slice(0, 3);
grid.innerHTML = featuredProducts.map(product => createProductCard(product)).join('');
if (typeof feather !== 'undefined') {
feather.replace();
}
}
// Load all products (products page)
function loadAllProducts() {
const grid = document.getElementById('all-products-grid');
if (!grid) return;
grid.innerHTML = products.map(product => createProductCard(product)).join('');
if (typeof feather !== 'undefined') {
feather.replace();
}
}
// Create product card HTML
function createProductCard(product) {
return `
${product.category}
${product.name}
${product.price.toFixed(2)}
${product.description}
${product.specs.map(spec => `
-
${spec}
`).join('')}
Request Quote
`;
}
// Load testimonials
function loadTestimonials() {
const grid = document.getElementById('testimonials-grid');
if (!grid) return;
grid.innerHTML = testimonials.map(t => `
${Array(t.rating).fill('').join('')}
"${t.content}"
${t.name}
${t.role}, ${t.company}
`).join('');
if (typeof feather !== 'undefined') {
feather.replace();
}
}
// Setup quote calculator
function setupQuoteCalculator() {
const form = document.getElementById('quote-form');
const result = document.getElementById('quote-result');
const priceEl = document.getElementById('quote-price');
if (!form) return;
form.addEventListener('submit', function(e) {
e.preventDefault();
const type = document.getElementById('pallet-type').value;
const quantity = parseInt(document.getElementById('quantity').value) || 1;
const location = document.getElementById('location').value;
const basePrice = pricing[type].base;
const locationMult = locationMultipliers[location];
const volumeDiscount = quantity >= 500 ? 0.85 : quantity >= 100 ? 0.9 : 1;
const total = basePrice * quantity * locationMult * volumeDiscount;
priceEl.textContent = ' + total.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
result.classList.remove('hidden');
// Animate the price
animateValue(priceEl, 0, total, 500);
});
}
// Animate number value
function animateValue(element, start, end, duration) {
const range = end - start;
const increment = end > start ? 1 : -1;
const stepTime = Math.abs(Math.floor(duration / (range / 100)));
let current = start;
const timer = setInterval(() => {
current += range / 20;
if ((increment > 0 && current >= end) || (increment < 0 && current <= end)) {
current = end;
clearInterval(timer);
}
element.textContent = ' + current.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}, stepTime);
}
// Submit quote request
function submitQuote() {
const type = document.getElementById('pallet-type').value;
const quantity = document.getElementById('quantity').value;
// Store in sessionStorage for contact form
sessionStorage.setItem('quoteType', type);
sessionStorage.setItem('quoteQuantity', quantity);
window.location.href = 'contact.html?subject=quote';
}
// Setup product filters
function setupProductFilters() {
const buttons = document.querySelectorAll('.filter-btn');
const cards = document.querySelectorAll('[data-category]');
if (!buttons.length) return;
buttons.forEach(btn => {
btn.addEventListener('click', () => {
// Update active state
buttons.forEach(b => {
b.classList.remove('active', 'bg-primary-600', 'text-white');
b.classList.add('bg-white', 'dark:bg-wood-800');
});
btn.classList.add('active', 'bg-primary-600', 'text-white');
btn.classList.remove('bg-white', 'dark:bg-wood-800');
// Filter cards
const filter = btn.dataset.filter;
cards.forEach(card => {
if (filter === 'all' || card.dataset.category === filter) {
card.style.display = 'block';
card.classList.add('animate-scale-in');
} else {
card.style.display = 'none';
}
});
});
});
}
// Setup forms
function setupForms() {
// Contact form
const contactForm = document.getElementById('contact-form');
if (contactForm) {
// Pre-fill if coming from quote
const urlParams = new URLSearchParams(window.location.search);
const subject = urlParams.get('subject');
if (subject === 'quote') {
const subjectSelect = contactForm.querySelector('select');
if (subjectSelect) subjectSelect.value = 'Request Quote';
}
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
showToast('Message sent successfully! We\'ll get back to you within 2 hours.');
this.reset();
});
}
// B2B form
const b2bForm = document.getElementById('b2b-form');
if (b2bForm) {
b2bForm.addEventListener('submit', function(e) {
e.preventDefault();
showToast('Consultation request submitted! Our B2B team will contact you shortly.');
this.reset();
});
}
}
// Show toast notification
function showToast(message) {
// Remove existing toast
const existing = document.querySelector('.toast');
if (existing) existing.remove();
const toast = document.createElement('div');
toast.className = 'toast';
toast.innerHTML = `
${message}
`;
document.body.appendChild(toast);
if (typeof feather !== 'undefined') {
feather.replace();
}
setTimeout(() => toast.classList.add('show'), 10);
setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => toast.remove(), 300);
}, 4000);
}
// Setup scroll animations
function setupScrollAnimations() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-slide-up');
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe sections for animation
document.querySelectorAll('section > div').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
observer.observe(el);
});
}
// Add CSS animation classes dynamically
const style = document.createElement('style');
style.textContent = `
.animate-slide-up {
animation: slideUp 0.6s ease-out forwards;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`;
document.head.appendChild(style);