484 lines
16 KiB
JavaScript
484 lines
16 KiB
JavaScript
// متغيرات عامة
|
|
let selectedProducts = [];
|
|
const maxCompareItems = 3;
|
|
|
|
// تهيئة صفحة البحث
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initializeSearch();
|
|
initializeComparison();
|
|
});
|
|
|
|
// تهيئة نظام البحث
|
|
function initializeSearch() {
|
|
const searchForm = document.getElementById('advanced-search');
|
|
const filters = document.querySelectorAll('select, input');
|
|
|
|
// معالجة نموذج البحث
|
|
searchForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
await performSearch();
|
|
});
|
|
|
|
// تحديث النتائج عند تغيير الفلاتر
|
|
filters.forEach(filter => {
|
|
filter.addEventListener('change', debounce(performSearch, 500));
|
|
});
|
|
}
|
|
|
|
// تنفيذ البحث
|
|
async function performSearch() {
|
|
const searchQuery = document.getElementById('search-query').value;
|
|
const productType = document.getElementById('product-type').value;
|
|
const minPrice = document.getElementById('min-price').value;
|
|
const maxPrice = document.getElementById('max-price').value;
|
|
const sortBy = document.getElementById('sort-by').value;
|
|
|
|
try {
|
|
const response = await fetch('/api/search.php', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
query: searchQuery,
|
|
type: productType,
|
|
minPrice,
|
|
maxPrice,
|
|
sortBy
|
|
})
|
|
});
|
|
|
|
if (!response.ok) throw new Error('فشل البحث');
|
|
|
|
const results = await response.json();
|
|
displayResults(results);
|
|
} catch (error) {
|
|
console.error('Search error:', error);
|
|
showError('حدث خطأ أثناء البحث. يرجى المحاولة مرة أخرى.');
|
|
}
|
|
}
|
|
|
|
// عرض نتائج البحث
|
|
function displayResults(results) {
|
|
const resultsContainer = document.getElementById('search-results');
|
|
|
|
if (!results.length) {
|
|
resultsContainer.innerHTML = '<div class="no-results">لم يتم العثور على نتائج</div>';
|
|
return;
|
|
}
|
|
|
|
resultsContainer.innerHTML = results.map(product => `
|
|
<div class="product-card" data-id="${product.id}">
|
|
<div class="product-image">
|
|
<img src="${product.image}" alt="${product.name}">
|
|
${product.badge ? `<span class="badge">${product.badge}</span>` : ''}
|
|
</div>
|
|
<div class="product-info">
|
|
<h3>${product.name}</h3>
|
|
<p>${product.description}</p>
|
|
<div class="product-price">${product.price} جنيه</div>
|
|
<div class="product-actions">
|
|
<button class="btn add-to-cart">أضف للسلة</button>
|
|
<button class="btn-secondary add-to-compare" onclick="toggleCompare(${product.id})">
|
|
<i class="fas fa-exchange-alt"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// نظام المقارنة
|
|
function initializeComparison() {
|
|
document.getElementById('compare-btn').addEventListener('click', () => {
|
|
if (selectedProducts.length > 1) {
|
|
window.location.href = `/compare.html?products=${selectedProducts.join(',')}`;
|
|
}
|
|
});
|
|
}
|
|
|
|
// إضافة/إزالة منتج من المقارنة
|
|
function toggleCompare(productId) {
|
|
const index = selectedProducts.indexOf(productId);
|
|
|
|
if (index === -1) {
|
|
if (selectedProducts.length >= maxCompareItems) {
|
|
alert(`يمكنك مقارنة ${maxCompareItems} منتجات كحد أقصى`);
|
|
return;
|
|
}
|
|
selectedProducts.push(productId);
|
|
} else {
|
|
selectedProducts.splice(index, 1);
|
|
}
|
|
|
|
updateComparisonUI();
|
|
}
|
|
|
|
// تحديث واجهة المقارنة
|
|
function updateComparisonUI() {
|
|
const compareBtn = document.getElementById('compare-btn');
|
|
const comparisonList = document.getElementById('comparison-list');
|
|
|
|
compareBtn.disabled = selectedProducts.length < 2;
|
|
|
|
// تحديث قائمة المنتجات المحددة للمقارنة
|
|
if (selectedProducts.length > 0) {
|
|
fetchProductsDetails(selectedProducts).then(products => {
|
|
comparisonList.innerHTML = products.map(product => `
|
|
<div class="comparison-item">
|
|
<img src="${product.image}" alt="${product.name}">
|
|
<span>${product.name}</span>
|
|
<button onclick="toggleCompare(${product.id})">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
`).join('');
|
|
});
|
|
} else {
|
|
comparisonList.innerHTML = '<p>اختر منتجات للمقارنة</p>';
|
|
}
|
|
}
|
|
|
|
// دالة مساعدة للحد من تكرار الطلبات
|
|
function debounce(func, wait) {
|
|
let timeout;
|
|
return function executedFunction(...args) {
|
|
const later = () => {
|
|
clearTimeout(timeout);
|
|
func(...args);
|
|
};
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
};
|
|
}
|
|
|
|
// عرض رسائل الخطأ
|
|
function showError(message) {
|
|
const resultsContainer = document.getElementById('search-results');
|
|
resultsContainer.innerHTML = `<div class="error-message">${message}</div>`;
|
|
}
|
|
|
|
// جلب تفاصيل المنتجات للمقارنة
|
|
async function fetchProductsDetails(productIds) {
|
|
try {
|
|
const response = await fetch('/api/products.php', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ ids: productIds })
|
|
});
|
|
|
|
if (!response.ok) throw new Error('فشل جلب تفاصيل المنتجات');
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error fetching product details:', error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const searchInput = document.querySelector('.search-input');
|
|
const searchResults = document.querySelector('.search-results');
|
|
const searchIcon = document.querySelector('.search-icon');
|
|
const voiceSearchBtn = document.querySelector('.voice-search-btn');
|
|
const categoryFilters = document.querySelectorAll('input[name="category"]');
|
|
const minPrice = document.getElementById('min-price');
|
|
const maxPrice = document.getElementById('max-price');
|
|
const sortBy = document.getElementById('sort-by');
|
|
|
|
let searchTimeout;
|
|
const debounceDelay = 300;
|
|
|
|
// تفعيل البحث عند الكتابة
|
|
searchInput.addEventListener('input', function() {
|
|
clearTimeout(searchTimeout);
|
|
if (this.value.length > 0) {
|
|
searchTimeout = setTimeout(() => {
|
|
performSearch();
|
|
searchResults.classList.add('active');
|
|
}, debounceDelay);
|
|
} else {
|
|
searchResults.classList.remove('active');
|
|
}
|
|
});
|
|
|
|
// إخفاء نتائج البحث عند النقر خارجها
|
|
document.addEventListener('click', function(e) {
|
|
if (!searchResults.contains(e.target) && !searchInput.contains(e.target)) {
|
|
searchResults.classList.remove('active');
|
|
}
|
|
});
|
|
|
|
// تفعيل البحث الصوتي
|
|
voiceSearchBtn.addEventListener('click', function() {
|
|
if ('webkitSpeechRecognition' in window) {
|
|
const recognition = new webkitSpeechRecognition();
|
|
recognition.lang = 'ar-SA';
|
|
recognition.continuous = false;
|
|
recognition.interimResults = false;
|
|
|
|
recognition.onstart = function() {
|
|
voiceSearchBtn.classList.add('listening');
|
|
};
|
|
|
|
recognition.onresult = function(event) {
|
|
const transcript = event.results[0][0].transcript;
|
|
searchInput.value = transcript;
|
|
performSearch();
|
|
searchResults.classList.add('active');
|
|
};
|
|
|
|
recognition.onerror = function(event) {
|
|
console.error('Speech recognition error:', event.error);
|
|
voiceSearchBtn.classList.remove('listening');
|
|
};
|
|
|
|
recognition.onend = function() {
|
|
voiceSearchBtn.classList.remove('listening');
|
|
};
|
|
|
|
recognition.start();
|
|
} else {
|
|
alert('عذراً، البحث الصوتي غير مدعوم في متصفحك');
|
|
}
|
|
});
|
|
|
|
// تحديث نتائج البحث عند تغيير الفلاتر
|
|
categoryFilters.forEach(filter => {
|
|
filter.addEventListener('change', performSearch);
|
|
});
|
|
minPrice.addEventListener('input', performSearch);
|
|
maxPrice.addEventListener('input', performSearch);
|
|
sortBy.addEventListener('change', performSearch);
|
|
|
|
// دالة البحث الرئيسية
|
|
function performSearch() {
|
|
const query = searchInput.value;
|
|
const selectedCategories = Array.from(categoryFilters)
|
|
.filter(checkbox => checkbox.checked)
|
|
.map(checkbox => checkbox.value);
|
|
const priceRange = {
|
|
min: minPrice.value ? parseInt(minPrice.value) : null,
|
|
max: maxPrice.value ? parseInt(maxPrice.value) : null
|
|
};
|
|
const sortValue = sortBy.value;
|
|
|
|
// محاكاة طلب API
|
|
fetchSearchResults(query, selectedCategories, priceRange, sortValue)
|
|
.then(displayResults)
|
|
.catch(error => console.error('Search error:', error));
|
|
}
|
|
|
|
// دالة جلب نتائج البحث من الخادم
|
|
async function fetchSearchResults(query, categories, priceRange, sort) {
|
|
// هنا يمكنك استبدال هذا بطلب API حقيقي
|
|
const mockResults = [
|
|
{
|
|
id: 1,
|
|
title: 'زيت اللافندر العطري',
|
|
category: 'زيوت عطرية',
|
|
price: 120,
|
|
image: 'images/products/lavender.jpg'
|
|
},
|
|
{
|
|
id: 2,
|
|
title: 'زيت الجوجوبا',
|
|
category: 'زيوت ثابتة',
|
|
price: 85,
|
|
image: 'images/products/jojoba.jpg'
|
|
}
|
|
];
|
|
|
|
return new Promise(resolve => {
|
|
setTimeout(() => resolve(mockResults), 300);
|
|
});
|
|
}
|
|
|
|
// دالة عرض نتائج البحث
|
|
function displayResults(results) {
|
|
const resultsContainer = document.querySelector('.search-results-list');
|
|
resultsContainer.innerHTML = '';
|
|
|
|
if (results.length === 0) {
|
|
resultsContainer.innerHTML = '<div class="no-results">لا توجد نتائج</div>';
|
|
return;
|
|
}
|
|
|
|
results.forEach(result => {
|
|
const resultItem = document.createElement('div');
|
|
resultItem.className = 'result-item';
|
|
resultItem.innerHTML = `
|
|
<img src="${result.image}" alt="${result.title}" class="result-image">
|
|
<div class="result-info">
|
|
<div class="result-title">${result.title}</div>
|
|
<div class="result-category">${result.category}</div>
|
|
</div>
|
|
<div class="result-price">${result.price} ر.س</div>
|
|
`;
|
|
resultItem.addEventListener('click', () => {
|
|
window.location.href = `/product/${result.id}`;
|
|
});
|
|
resultsContainer.appendChild(resultItem);
|
|
});
|
|
}
|
|
});
|
|
|
|
class ProductSearch {
|
|
constructor() {
|
|
this.searchInput = document.querySelector('.search-input');
|
|
this.searchResults = document.querySelector('.search-results');
|
|
this.filterForm = document.querySelector('.search-filters');
|
|
this.initializeSearch();
|
|
}
|
|
|
|
initializeSearch() {
|
|
// إضافة مستمعي الأحداث
|
|
this.searchInput?.addEventListener('input', debounce(() => this.handleSearch(), 300));
|
|
this.filterForm?.addEventListener('change', () => this.handleSearch());
|
|
|
|
// إضافة مستمع لإغلاق نتائج البحث عند النقر خارجها
|
|
document.addEventListener('click', (e) => {
|
|
if (!e.target.closest('.search-container')) {
|
|
this.hideResults();
|
|
}
|
|
});
|
|
}
|
|
|
|
async handleSearch() {
|
|
const query = this.searchInput?.value.trim();
|
|
if (!query) {
|
|
this.hideResults();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// جمع معايير التصفية
|
|
const filters = this.getFilters();
|
|
|
|
// إجراء البحث
|
|
const response = await fetch('/api/search.php', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
query,
|
|
...filters
|
|
})
|
|
});
|
|
|
|
if (!response.ok) throw new Error('فشل البحث');
|
|
|
|
const results = await response.json();
|
|
this.displayResults(results);
|
|
} catch (error) {
|
|
console.error('Search error:', error);
|
|
this.showError('حدث خطأ أثناء البحث');
|
|
}
|
|
}
|
|
|
|
getFilters() {
|
|
const filters = {
|
|
category: [],
|
|
priceRange: {
|
|
min: null,
|
|
max: null
|
|
},
|
|
sortBy: 'relevance'
|
|
};
|
|
|
|
if (this.filterForm) {
|
|
// جمع الفئات المحددة
|
|
const categoryInputs = this.filterForm.querySelectorAll('input[name="category"]:checked');
|
|
filters.category = Array.from(categoryInputs).map(input => input.value);
|
|
|
|
// جمع نطاق السعر
|
|
const minPrice = this.filterForm.querySelector('#min-price')?.value;
|
|
const maxPrice = this.filterForm.querySelector('#max-price')?.value;
|
|
if (minPrice) filters.priceRange.min = parseFloat(minPrice);
|
|
if (maxPrice) filters.priceRange.max = parseFloat(maxPrice);
|
|
|
|
// جمع معيار الترتيب
|
|
filters.sortBy = this.filterForm.querySelector('#sort-by')?.value || 'relevance';
|
|
}
|
|
|
|
return filters;
|
|
}
|
|
|
|
displayResults(results) {
|
|
if (!this.searchResults) return;
|
|
|
|
if (results.length === 0) {
|
|
this.searchResults.innerHTML = `
|
|
<div class="no-results">
|
|
<i class="fas fa-search"></i>
|
|
<p>لم يتم العثور على نتائج</p>
|
|
</div>
|
|
`;
|
|
} else {
|
|
this.searchResults.innerHTML = `
|
|
<div class="results-list">
|
|
${results.map(product => `
|
|
<a href="${product.url}" class="result-item">
|
|
<img src="${product.image}" alt="${product.name}">
|
|
<div class="result-info">
|
|
<h4>${this.highlightQuery(product.name)}</h4>
|
|
<p>${this.highlightQuery(product.description)}</p>
|
|
<span class="price">${product.price} ريال</span>
|
|
</div>
|
|
</a>
|
|
`).join('')}
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
this.showResults();
|
|
}
|
|
|
|
highlightQuery(text) {
|
|
if (!this.searchInput?.value.trim()) return text;
|
|
|
|
const query = this.searchInput.value.trim();
|
|
const regex = new RegExp(`(${query})`, 'gi');
|
|
return text.replace(regex, '<mark>$1</mark>');
|
|
}
|
|
|
|
showResults() {
|
|
this.searchResults?.classList.add('show');
|
|
}
|
|
|
|
hideResults() {
|
|
this.searchResults?.classList.remove('show');
|
|
}
|
|
|
|
showError(message) {
|
|
if (!this.searchResults) return;
|
|
|
|
this.searchResults.innerHTML = `
|
|
<div class="search-error">
|
|
<i class="fas fa-exclamation-circle"></i>
|
|
<p>${message}</p>
|
|
</div>
|
|
`;
|
|
this.showResults();
|
|
}
|
|
}
|
|
|
|
// دالة مساعدة للحد من تكرار استدعاء البحث
|
|
function debounce(func, wait) {
|
|
let timeout;
|
|
return function executedFunction(...args) {
|
|
const later = () => {
|
|
clearTimeout(timeout);
|
|
func(...args);
|
|
};
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
};
|
|
}
|
|
|
|
// تهيئة نظام البحث
|
|
const productSearch = new ProductSearch();
|