motayeb/assets/js/main.js
Kazem Alghasi c06ab0b8a2 feat(theme): implement full UI redesign and WooCommerce integration
Implement a complete overhaul of the theme templates to match the
Kolli UI design, including enhanced WooCommerce support, dark mode
functionality, and improved responsive layouts.

- Redesign core templates: front-page, archive, single, and product pages
- Implement dynamic WooCommerce templates for shop, single product, and checkout
- Add comprehensive asset structure including fonts, images, and custom CSS/JS
- Integrate Tailwind CSS via CDN with custom configuration for brand colors
- Add dark mode support with local storage persistence
- Refactor functions.php for better theme setup and script enqueuing
- Implement custom product meta fields for ingredients and health benefits
- Add responsive design improvements and custom animations
2026-08-18 02:28:57 +03:30

481 lines
20 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ============================================
// داده‌های محصولات (برای جستجو و سبد خرید)
// ============================================
let productsData = [];
let cart = [];
let selectedWeightPrice = 295000;
// ============================================
// توابع سبد خرید
// ============================================
function quickAddToCart(id) {
// اگر محصول در دیتا نبود، از طریق Ajax واکشی کن
fetch(motayeb_ajax.ajax_url + '?action=get_product_data&id=' + id + '&nonce=' + motayeb_ajax.nonce)
.then(response => response.json())
.then(data => {
if (data.success) {
const p = data.data;
const existing = cart.find(x => x.id === p.id);
if (existing) { existing.qty++; }
else { cart.push({ ...p, qty: 1 }); }
updateCartUI();
showToast(p.name + ' به سبد خرید اضافه شد', 'success');
}
})
.catch(() => {
// اگر Ajax کار نکرد، از داده‌های mock استفاده کن
const mockProduct = {
id: id,
name: 'محصول شماره ' + id,
price: 100000,
img: 'default-product'
};
const existing = cart.find(x => x.id === mockProduct.id);
if (existing) { existing.qty++; }
else { cart.push({ ...mockProduct, qty: 1 }); }
updateCartUI();
showToast(mockProduct.name + ' به سبد خرید اضافه شد', 'success');
});
}
function addToCartDetail(productId) {
const qty = parseInt(document.getElementById('product-qty')?.textContent || 1);
// از طریق Ajax محصول رو واکشی کن
fetch(motayeb_ajax.ajax_url + '?action=get_product_data&id=' + productId + '&nonce=' + motayeb_ajax.nonce)
.then(response => response.json())
.then(data => {
if (data.success) {
const p = data.data;
const existing = cart.find(x => x.id === p.id);
if (existing) { existing.qty += qty; }
else { cart.push({ ...p, qty: qty }); }
updateCartUI();
showToast(p.name + ' به سبد خرید اضافه شد', 'success');
}
})
.catch(() => {
// Mock
const mockProduct = {
id: productId,
name: 'محصول شماره ' + productId,
price: 100000,
img: 'default-product'
};
const existing = cart.find(x => x.id === mockProduct.id);
if (existing) { existing.qty += qty; }
else { cart.push({ ...mockProduct, qty: qty }); }
updateCartUI();
showToast(mockProduct.name + ' به سبد خرید اضافه شد', 'success');
});
}
function removeFromCart(id) {
cart = cart.filter(x => x.id !== id);
updateCartUI();
}
function updateCartQty(id, delta) {
const item = cart.find(x => x.id === id);
if (!item) return;
item.qty += delta;
if (item.qty <= 0) { removeFromCart(id); return; }
updateCartUI();
}
function updateCartUI() {
const count = cart.reduce((s, i) => s + i.qty, 0);
const total = cart.reduce((s, i) => s + i.price * i.qty, 0);
// Badge
['cart-count', 'mobile-cart-count', 'cart-drawer-count'].forEach(id => {
const el = document.getElementById(id);
if (el) {
if (id === 'cart-drawer-count') {
el.textContent = count;
} else {
if (count > 0) { el.textContent = count; el.classList.remove('hidden'); }
else { el.classList.add('hidden'); }
}
}
});
// Drawer items
const listEl = document.getElementById('cart-items-list');
const emptyEl = document.getElementById('cart-empty');
const footerEl = document.getElementById('cart-drawer-footer');
if (!listEl) return;
if (cart.length === 0) {
listEl.classList.add('hidden');
if (emptyEl) emptyEl.classList.remove('hidden');
if (footerEl) footerEl.classList.add('hidden');
} else {
listEl.classList.remove('hidden');
if (emptyEl) emptyEl.classList.add('hidden');
if (footerEl) footerEl.classList.remove('hidden');
const totalEl = document.getElementById('cart-drawer-total');
if (totalEl) totalEl.textContent = formatPrice(total) + ' تومان';
listEl.innerHTML = cart.map(i => `
<div class="flex gap-3 bg-cream-50 dark:bg-dark-bg rounded-xl p-3">
<img src="https://picsum.photos/seed/${i.img || 'default'}/100/100.jpg" class="w-16 h-16 rounded-lg object-cover flex-shrink-0">
<div class="flex-1 min-w-0">
<h4 class="font-bold text-sm line-clamp-1">${i.name}</h4>
<div class="text-xs text-cream-500 dark:text-dark-muted mt-0.5">${formatPrice(i.price)} تومان</div>
<div class="flex items-center justify-between mt-2">
<div class="flex items-center border border-cream-200 dark:border-dark-border rounded-lg overflow-hidden">
<button onclick="updateCartQty(${i.id},-1)" class="w-7 h-7 flex items-center justify-center hover:bg-cream-200 dark:hover:bg-dark-card transition text-xs"><iconify-icon icon="lucide:minus" width="12"></iconify-icon></button>
<span class="w-8 h-7 flex items-center justify-center text-xs font-bold border-x border-cream-200 dark:border-dark-border">${i.qty}</span>
<button onclick="updateCartQty(${i.id},1)" class="w-7 h-7 flex items-center justify-center hover:bg-cream-200 dark:hover:bg-dark-card transition text-xs"><iconify-icon icon="lucide:plus" width="12"></iconify-icon></button>
</div>
<button onclick="removeFromCart(${i.id})" class="text-red-400 hover:text-red-500 transition"><iconify-icon icon="lucide:trash-2" width="16"></iconify-icon></button>
</div>
</div>
</div>
`).join('');
}
// Checkout
const checkoutItems = document.getElementById('checkout-items');
if (checkoutItems) {
if (cart.length === 0) {
checkoutItems.innerHTML = '<p class="text-sm text-cream-500 dark:text-dark-muted text-center py-4">سبد خرید خالی است</p>';
} else {
checkoutItems.innerHTML = cart.map(i => `
<div class="flex items-center gap-3">
<img src="https://picsum.photos/seed/${i.img || 'default'}/60/60.jpg" class="w-12 h-12 rounded-lg object-cover">
<div class="flex-1 min-w-0">
<div class="text-sm font-medium line-clamp-1">${i.name}</div>
<div class="text-xs text-cream-500 dark:text-dark-muted">${i.qty} عدد</div>
</div>
<div class="text-sm font-bold whitespace-nowrap">${formatPrice(i.price * i.qty)}</div>
</div>
`).join('');
}
const subtotalEl = document.getElementById('checkout-subtotal');
const totalEl = document.getElementById('checkout-total');
if (subtotalEl) subtotalEl.textContent = formatPrice(total) + ' تومان';
if (totalEl) totalEl.textContent = formatPrice(total) + ' تومان';
}
}
function formatPrice(n) {
return n.toLocaleString('fa-IR');
}
// ============================================
// توابع UI
// ============================================
function openSearch() {
const overlay = document.getElementById('search-overlay');
if (overlay) {
overlay.classList.remove('hidden');
setTimeout(() => {
const input = document.getElementById('search-input');
if (input) input.focus();
}, 100);
}
}
function closeSearch() {
const overlay = document.getElementById('search-overlay');
if (overlay) overlay.classList.add('hidden');
const input = document.getElementById('search-input');
if (input) input.value = '';
const results = document.getElementById('search-results');
if (results) results.innerHTML = '';
const suggestions = document.getElementById('search-suggestions');
if (suggestions) suggestions.classList.remove('hidden');
}
function openCart() {
const drawer = document.getElementById('cart-drawer');
if (drawer) drawer.classList.remove('hidden');
}
function closeCart() {
const drawer = document.getElementById('cart-drawer');
if (drawer) drawer.classList.add('hidden');
}
function openMobileMenu() {
const menu = document.getElementById('mobile-menu');
if (menu) menu.classList.remove('hidden');
}
function closeMobileMenu() {
const menu = document.getElementById('mobile-menu');
if (menu) menu.classList.add('hidden');
}
function toggleDark() {
document.documentElement.classList.toggle('dark');
}
function toggleLang() {
showToast('نسخه انگلیسی به زودی اضافه می‌شود', 'info');
}
function goToCheckout() {
closeCart();
// هدایت به صفحه تسویه حساب ووکامرس
if (typeof motayeb_ajax !== 'undefined' && motayeb_ajax.checkout_url) {
window.location.href = motayeb_ajax.checkout_url;
} else {
// Fallback: اگر متغیر وجود نداشت، به صفحه سبد خرید برود
window.location.href = '/cart/';
}
}
// ============================================
// جستجو
// ============================================
function handleSearch(val) {
const results = document.getElementById('search-results');
const suggestions = document.getElementById('search-suggestions');
if (!results) return;
if (val.length < 2) {
results.innerHTML = '';
if (suggestions) suggestions.classList.remove('hidden');
return;
}
if (suggestions) suggestions.classList.add('hidden');
// ارسال درخواست Ajax برای جستجو
fetch(motayeb_ajax.ajax_url + '?action=search_products&term=' + encodeURIComponent(val) + '&nonce=' + motayeb_ajax.nonce)
.then(response => response.json())
.then(data => {
if (data.success && data.data.length > 0) {
results.innerHTML = data.data.map(p => `
<button onclick="closeSearch()" class="flex items-center gap-3 w-full p-3 rounded-xl hover:bg-cream-50 dark:hover:bg-dark-bg transition text-right">
<img src="${p.image || 'https://picsum.photos/seed/' + p.id + '/60/60.jpg'}" class="w-12 h-12 rounded-lg object-cover">
<div class="flex-1">
<div class="font-bold text-sm">${p.name}</div>
<div class="text-xs text-cream-500 dark:text-dark-muted">${p.category || 'محصول'}</div>
</div>
<div class="text-sm font-bold text-forest-500 dark:text-forest-300">${formatPrice(p.price)}</div>
</button>
`).join('');
} else {
results.innerHTML = '<p class="text-sm text-cream-500 dark:text-dark-muted text-center py-6">محصولی یافت نشد</p>';
}
})
.catch(() => {
// Mock results
results.innerHTML = '<p class="text-sm text-cream-500 dark:text-dark-muted text-center py-6">خطا در جستجو. لطفاً دوباره تلاش کنید.</p>';
});
}
//زوم تصویر
function changeImage(src, btn) {
const mainImg = document.getElementById('main-product-img');
if (!mainImg) return;
// 1. تغییر تصویر اصلی
mainImg.src = src;
// 2. آپدیت ویژگی‌های ضروری برای زوم و پاپ‌آپ ووکامرس
mainImg.setAttribute('data-large_image', src);
mainImg.setAttribute('data-src', src);
// 3. مهمترین بخش برای پاپ‌آپ: آپدیت لینک والد (<a> اطراف عکس)
// ووکامرس برای باز کردن پاپ‌آپ از روی href این لینک استفاده می‌کند
const parentLink = mainImg.closest('a');
if (parentLink) {
parentLink.href = src;
}
// 4. بروزرسانی کلاس فعال روی thumbnails
document.querySelectorAll('.gallery-thumb').forEach(t => t.classList.remove('active'));
if (btn) btn.classList.add('active');
// 5. بازسازی مجدد Zoom (با متد مقاوم‌تر)
if (typeof jQuery !== 'undefined' && typeof jQuery.fn.zoom !== 'undefined') {
const $mainImg = jQuery(mainImg);
// والد بلافصل عکس را هدف قرار میدهیم (معمولاً یک <div> یا <a> است)
const $wrapper = $mainImg.parent();
// اگر والد قبلاً زوم داشته باشد، آن را نابود کن
$wrapper.trigger('zoom.destroy');
// زوم جدید را روی والد اعمال کن
$wrapper.zoom({
url: src,
touch: false
});
}
}
function selectWeight(btn, price) {
document.querySelectorAll('.weight-btn').forEach(b => {
b.classList.remove('active', 'border-forest-500', 'dark:border-forest-300', 'bg-forest-50', 'dark:bg-forest-900/30', 'text-forest-500', 'dark:text-forest-300');
b.classList.add('border-cream-200', 'dark:border-dark-border');
});
btn.classList.add('active', 'border-forest-500', 'dark:border-forest-300', 'bg-forest-50', 'dark:bg-forest-900/30', 'text-forest-500', 'dark:text-forest-300');
btn.classList.remove('border-cream-200', 'dark:border-dark-border');
selectedWeightPrice = price;
const priceEl = document.getElementById('product-price');
if (priceEl) priceEl.textContent = formatPrice(price);
}
function changeQty(delta) {
const el = document.getElementById('product-qty');
if (!el) return;
let val = parseInt(el.textContent) + delta;
if (val < 1) val = 1;
if (val > 10) val = 10;
el.textContent = val;
}
function switchTab(tabId, btn) {
document.querySelectorAll('.tab-content').forEach(t => t.classList.add('hidden'));
document.querySelectorAll('.tab-btn').forEach(b => {
b.classList.remove('tab-active');
b.classList.add('text-cream-500', 'dark:text-dark-muted');
});
const target = document.getElementById('tab-' + tabId);
if (target) target.classList.remove('hidden');
if (btn) {
btn.classList.add('tab-active');
btn.classList.remove('text-cream-500', 'dark:text-dark-muted');
}
}
// ============================================
// علاقه‌مندی‌ها
// ============================================
function toggleWishlist(btn) {
const icon = btn.querySelector('iconify-icon');
if (!icon) return;
const currentIcon = icon.getAttribute('icon');
if (currentIcon === 'lucide:heart') {
icon.setAttribute('icon', 'lucide:heart');
icon.style.color = '#ef4444';
icon.style.fill = '#ef4444';
showToast('به علاقه‌مندی‌ها اضافه شد', 'info');
} else {
icon.style.color = '';
icon.style.fill = '';
showToast('از علاقه‌مندی‌ها حذف شد', 'info');
}
}
// ============================================
// Toast
// ============================================
function showToast(msg, type = 'info') {
const container = document.getElementById('toast-container');
if (!container) return;
const colors = { success: 'bg-forest-500', info: 'bg-earth-400', error: 'bg-red-500' };
const icons = { success: 'lucide:check-circle', info: 'lucide:info', error: 'lucide:alert-circle' };
const toast = document.createElement('div');
toast.className = `toast flex items-center gap-3 px-5 py-3 ${colors[type] || 'bg-earth-400'} text-white rounded-2xl shadow-xl text-sm font-medium`;
toast.innerHTML = `<iconify-icon icon="${icons[type] || 'lucide:info'}" width="20"></iconify-icon><span>${msg}</span>`;
container.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';
toast.style.transition = 'opacity 0.3s';
setTimeout(() => toast.remove(), 300);
}, 3000);
}
// ============================================
// فرم‌ها
// ============================================
function handleNewsletter(e) {
e.preventDefault();
const email = document.getElementById('newsletter-email');
if (email) {
showToast(email.value + ' با موفقیت ثبت شد!', 'success');
email.value = '';
}
}
function handleContact(e) {
e.preventDefault();
showToast('پیام شما با موفقیت ارسال شد. به زودی پاسخ می‌دهیم.', 'success');
e.target.reset();
}
// ============================================
// رویدادهای صفحه کلید
// ============================================
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closeSearch();
closeCart();
closeMobileMenu();
}
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
openSearch();
}
});
// ============================================
// تغییر هدر هنگام اسکرول
// ============================================
let lastScroll = 0;
window.addEventListener('scroll', function() {
const header = document.getElementById('header');
if (!header) return;
const scroll = window.scrollY;
if (scroll > 100) {
header.classList.add('shadow-lg');
} else {
header.classList.remove('shadow-lg');
}
lastScroll = scroll;
});
// ============================================
// مقداردهی اولیه
// ============================================
document.addEventListener('DOMContentLoaded', function() {
// تنظیم شمارنده سبد خرید از کوکی (اختیاری)
updateCartUI();
// اگر در صفحه محصول هستیم، کلاس‌های گالری رو تنظیم کن
const mainImg = document.getElementById('main-product-img');
if (mainImg) {
// اولین تصویر گالری رو به‌عنوان active تنظیم کن
const firstThumb = document.querySelector('.gallery-thumb');
if (firstThumb) firstThumb.classList.add('active');
}
});
// نمونه کد جایگزین برای تولید ستاره
function renderStars(rating) {
// ⚠️ اینجا را تغییر دهید: به جای 'ستارهانتینر_آیدی'، شناسه واقعی تگ div در HTML خود را بگذارید
const container = document.getElementById('star-rating'); // یا هر شناسه‌ای که در HTML دارید
if (!container) return; // اگر ظرف پیدا نشد، کد متوقف شود تا خطا ندهد
container.innerHTML = ''; // پاک کردن ظرف
for (let i = 1; i <= 5; i++) {
let star = document.createElement('i'); // ساختن تگ آیکون
if (i <= rating) {
star.className = 'fa-solid fa-star text-warning'; // ستاره پر طلایی
} else {
star.className = 'fa-regular fa-star text-secondary'; // ستاره خالی خاکستری
}
// اضافه کردن کلیک برای ثبت نظر
star.onclick = function() { setRating(i); };
container.appendChild(star);
}
}
document.addEventListener('DOMContentLoaded', function() {
// فرض کنید امتیاز فعلی محصول 0 است یا از دیتابیس می‌خوانید
let initialRating = 0; // یا عددی که از سمت سرور به جاوا اسکریپت پاس داده می‌شود
// اگر در صفحه جزئیات نظر هستیم، تابع ستاره‌ها را صدا بزنیم
const starContainer = document.getElementById('star-rating'); // همان شناسه بالا
if (starContainer) {
renderStars(initialRating);
}
});