load product ajax
This commit is contained in:
parent
8548016200
commit
80f6dc8612
|
|
@ -12,27 +12,66 @@ use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class ProductController extends Controller
|
class ProductController extends Controller
|
||||||
{
|
{
|
||||||
public function index(Request $request)
|
public function genders(Request $request)
|
||||||
|
{
|
||||||
|
$genderRepository = new GenderRepository;
|
||||||
|
$genders = $genderRepository->getList([]);
|
||||||
|
|
||||||
|
// Render gender links HTML
|
||||||
|
$genderHtml = '';
|
||||||
|
$currentGenderId = $request->input('current_gender');
|
||||||
|
|
||||||
|
foreach ($genders as $gender) {
|
||||||
|
$isActive = $currentGenderId == $gender->id;
|
||||||
|
$genderHtml .= '<li class="nav-item mb-1">';
|
||||||
|
$genderHtml .= '<a class="nav-link d-block fw-normal p-0 ' . ($isActive ? 'active text-primary' : '') . '" ';
|
||||||
|
$genderHtml .= 'href="#" data-gender-id="' . $gender->id . '">';
|
||||||
|
$genderHtml .= $gender->name;
|
||||||
|
$genderHtml .= '</a></li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'genders' => $genderHtml
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function categories(Request $request)
|
||||||
|
{
|
||||||
|
$categoryRepository = new CategoryRepository;
|
||||||
|
$categories = $categoryRepository->getList([]);
|
||||||
|
|
||||||
|
// Render category links HTML
|
||||||
|
$categoryHtml = '';
|
||||||
|
$currentCategoryId = $request->input('current_category');
|
||||||
|
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
$isActive = $currentCategoryId == $category->id;
|
||||||
|
$categoryHtml .= '<li class="nav-item mb-1">';
|
||||||
|
$categoryHtml .= '<a class="nav-link d-block fw-normal p-0 ' . ($isActive ? 'active text-primary' : '') . '" ';
|
||||||
|
$categoryHtml .= 'href="#" data-category-id="' . $category->id . '">';
|
||||||
|
$categoryHtml .= $category->name;
|
||||||
|
$categoryHtml .= '</a></li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'categories' => $categoryHtml
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ajax(Request $request)
|
||||||
{
|
{
|
||||||
$limit = 20;
|
$limit = 20;
|
||||||
$page = $request->page ?? 1;
|
$page = $request->page ?? 1;
|
||||||
|
|
||||||
$search = $request->search;
|
$search = $request->search;
|
||||||
|
|
||||||
$filter = $request->filter ?? [];
|
$filter = $request->filter ?? [];
|
||||||
$sortBy = $request->sort_by ?? 'relevance';
|
$sortBy = $request->sort_by ?? 'relevance';
|
||||||
|
|
||||||
$price_range_start = $request->price_range_start ?? null;
|
$price_range_start = $request->price_range_start ?? null;
|
||||||
$price_range_end = $request->price_range_end ?? null;
|
$price_range_end = $request->price_range_end ?? null;
|
||||||
|
|
||||||
$genderRepository = new GenderRepository;
|
|
||||||
$categoryRepository = new CategoryRepository;
|
|
||||||
|
|
||||||
$genders = $genderRepository->getList([]);
|
|
||||||
$categories = $categoryRepository->getList([]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$userId = $user ? $user->id : 0;
|
$userId = $user ? $user->id : 0;
|
||||||
[$location_id, $is_consignment] = Cache::remember('employee_user_'.$userId, 60 * 60 * 24, function () use ($user) {
|
[$location_id, $is_consignment] = Cache::remember('employee_user_'.$userId, 60 * 60 * 24, function () use ($user) {
|
||||||
|
|
@ -63,7 +102,17 @@ class ProductController extends Controller
|
||||||
'price_range_end' => $price_range_end,
|
'price_range_end' => $price_range_end,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Render product cards HTML
|
||||||
|
$productHtml = '';
|
||||||
|
foreach ($products as $product) {
|
||||||
|
$productHtml .= '<div class="col-6 col-md-4 mb-2 mb-sm-3 mb-md-0">';
|
||||||
|
$productHtml .= view('components.home.product-card', ['product' => $product])->render();
|
||||||
|
$productHtml .= '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// filter
|
||||||
|
$filter = $request->filter ?? [];
|
||||||
if (isset($filter['category']) && $filter['category']){
|
if (isset($filter['category']) && $filter['category']){
|
||||||
$category = StoreCategory::find($filter['category']);
|
$category = StoreCategory::find($filter['category']);
|
||||||
|
|
||||||
|
|
@ -87,16 +136,32 @@ class ProductController extends Controller
|
||||||
|
|
||||||
$filters = $filter;
|
$filters = $filter;
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'filters' => $filters,
|
||||||
|
'products' => $productHtml,
|
||||||
|
'count' => count($products),
|
||||||
|
'has_more' => count($products) >= $limit
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
$productRepository = new ProductRepository;
|
||||||
|
$products = [];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$filters = [];
|
||||||
|
|
||||||
$min_max_price = $productRepository->getMinMaxPrice();
|
$min_max_price = $productRepository->getMinMaxPrice();
|
||||||
|
|
||||||
|
|
||||||
return view('shop.catalog-fashion', [
|
return view('shop.catalog-fashion', [
|
||||||
'filters' => $filters,
|
|
||||||
'genders' => $genders,
|
|
||||||
'categories' => $categories,
|
|
||||||
|
|
||||||
'products' => $products,
|
'products' => $products,
|
||||||
'page' => $page,
|
|
||||||
'min_max_price' => $min_max_price,
|
'min_max_price' => $min_max_price,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,28 +33,8 @@
|
||||||
data-bs-target="#filterSidebar" aria-label="Close"></button>
|
data-bs-target="#filterSidebar" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="offcanvas-body flex-column pt-2 py-lg-0">
|
<div class="offcanvas-body flex-column pt-2 py-lg-0 filter-sidebar">
|
||||||
@if (count($filters) > 0)
|
|
||||||
<!-- Selected filters + Sorting -->
|
|
||||||
<div class="pb-4 mb-2 mb-xl-3">
|
|
||||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
|
||||||
<h4 class="h6 mb-0">Filter</h4>
|
|
||||||
<a type="button" href="{{ route('product.index') }}"
|
|
||||||
class="btn btn-sm btn-secondary bg-transparent border-0 text-decoration-underline p-0 ms-2">
|
|
||||||
Clear all
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex flex-wrap gap-2">
|
|
||||||
@foreach ($filters as $key => $filter)
|
|
||||||
<a href="{{ route('product.index',[http_build_query(request()->except('filter.'.$key))]) }}" type="button" class="btn btn-sm btn-secondary">
|
|
||||||
<i class="ci-close fs-sm ms-n1 me-1"></i>
|
|
||||||
{{ $filter }}
|
|
||||||
</a>
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="accordion">
|
<div class="accordion">
|
||||||
|
|
||||||
|
|
@ -71,14 +51,8 @@
|
||||||
aria-labelledby="headingGenders">
|
aria-labelledby="headingGenders">
|
||||||
<div class="accordion-body p-0 pb-4 mb-1 mb-xl-2">
|
<div class="accordion-body p-0 pb-4 mb-1 mb-xl-2">
|
||||||
<div style="height: 220px" data-simplebar data-simplebar-auto-hide="false">
|
<div style="height: 220px" data-simplebar data-simplebar-auto-hide="false">
|
||||||
<ul class="nav flex-column gap-2 pe-3">
|
<ul class="nav flex-column gap-2 pe-3" id="genders-list">
|
||||||
@foreach ($genders as $gender)
|
<!-- Genders will be loaded here via AJAX -->
|
||||||
<li class="nav-item mb-1">
|
|
||||||
<a class="nav-link d-block fw-normal p-0" href="{{ route('product.index', array_merge(request()->except('filter[gender]'), ['filter[gender]' => $gender->id])) }}">
|
|
||||||
{{ $gender->name }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
@endforeach
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -97,14 +71,8 @@
|
||||||
aria-labelledby="headingCategories">
|
aria-labelledby="headingCategories">
|
||||||
<div class="accordion-body p-0 pb-4 mb-1 mb-xl-2">
|
<div class="accordion-body p-0 pb-4 mb-1 mb-xl-2">
|
||||||
<div style="height: 220px" data-simplebar data-simplebar-auto-hide="false">
|
<div style="height: 220px" data-simplebar data-simplebar-auto-hide="false">
|
||||||
<ul class="nav flex-column gap-2 pe-3">
|
<ul class="nav flex-column gap-2 pe-3" id="categories-list">
|
||||||
@foreach ($categories as $category)
|
<!-- Categories will be loaded here via AJAX -->
|
||||||
<li class="nav-item mb-1">
|
|
||||||
<a class="nav-link d-block fw-normal p-0" href="{{ route('product.index', array_merge(request()->except('filter[category]'), ['filter[category]' => $category->id])) }}">
|
|
||||||
{{ $category->name }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
@endforeach
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -471,7 +439,7 @@
|
||||||
|
|
||||||
<!-- Sorting -->
|
<!-- Sorting -->
|
||||||
<div class="d-sm-flex align-items-center justify-content-between mt-n2 mb-3 mb-sm-4">
|
<div class="d-sm-flex align-items-center justify-content-between mt-n2 mb-3 mb-sm-4">
|
||||||
<div class="fs-sm text-body-emphasis text-nowrap">Found <span class="fw-semibold">{{ count($products) }}</span>
|
<div class="fs-sm text-body-emphasis text-nowrap">Found <span class="fw-semibold" id="product-count">Loading...</span>
|
||||||
items
|
items
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center text-nowrap">
|
<div class="d-flex align-items-center text-nowrap">
|
||||||
|
|
@ -495,18 +463,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row gy-4 gy-md-5 pb-4 pb-md-5">
|
<div class="row gy-4 gy-md-5 pb-4 pb-md-5" id="products-container">
|
||||||
|
<!-- Products will be loaded here via AJAX -->
|
||||||
@foreach ($products as $key => $value)
|
</div>
|
||||||
<!-- Item -->
|
|
||||||
<div class="col-6 col-md-4 mb-2 mb-sm-3 mb-md-0">
|
|
||||||
<x-home.product-card :product="$value" />
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Banner -->
|
|
||||||
{{-- <div class="col-12 col-md-8 mb-2 mb-sm-3 mb-md-0">
|
{{-- <div class="col-12 col-md-8 mb-2 mb-sm-3 mb-md-0">
|
||||||
<div
|
<div
|
||||||
class="position-relative bg-body-tertiary text-center rounded-4 p-4 p-sm-5 py-md-4 py-xl-5">
|
class="position-relative bg-body-tertiary text-center rounded-4 p-4 p-sm-5 py-md-4 py-xl-5">
|
||||||
|
|
@ -551,7 +510,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Show more button -->
|
<!-- Show more button -->
|
||||||
<a href="{{ route('product.index', array_merge(request()->except('page'), ['page' => $page + 1])) }}" type="button" class="btn btn-lg btn-outline-secondary w-100">
|
<a href="{{ route('product.index', array_merge(request()->except('page'), ['page' => 1])) }}" type="button" class="btn btn-lg btn-outline-secondary w-100">
|
||||||
Show more
|
Show more
|
||||||
<i class="ci-chevron-down fs-xl ms-2 me-n1"></i>
|
<i class="ci-chevron-down fs-xl ms-2 me-n1"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -635,6 +594,264 @@
|
||||||
<i class="ci-filter fs-base me-2"></i>
|
<i class="ci-filter fs-base me-2"></i>
|
||||||
Filters
|
Filters
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
loadGenders();
|
||||||
|
loadCategories();
|
||||||
|
loadProducts();
|
||||||
|
|
||||||
|
// Handle sort change
|
||||||
|
const sortSelect = document.querySelector('select[onchange*="sort_by"]');
|
||||||
|
if (sortSelect) {
|
||||||
|
sortSelect.removeAttribute('onchange');
|
||||||
|
sortSelect.addEventListener('change', function() {
|
||||||
|
loadProducts({ sort_by: this.value });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle price range changes
|
||||||
|
const priceInputs = document.querySelectorAll('[data-range-slider-min], [data-range-slider-max]');
|
||||||
|
priceInputs.forEach(input => {
|
||||||
|
input.addEventListener('change', function() {
|
||||||
|
const minVal = document.querySelector('[data-range-slider-min]').value;
|
||||||
|
const maxVal = document.querySelector('[data-range-slider-max]').value;
|
||||||
|
loadProducts({
|
||||||
|
price_range_start: minVal || null,
|
||||||
|
price_range_end: maxVal || null
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attach initial filter event listeners
|
||||||
|
attachFilterEventListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
function removeFilter(filterKey) {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
urlParams.delete(`filter[${filterKey}]`);
|
||||||
|
|
||||||
|
// Convert URLSearchParams to object for loadProducts
|
||||||
|
const params = {};
|
||||||
|
for (const [key, value] of urlParams.entries()) {
|
||||||
|
params[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadProducts(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearAllFilters() {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
|
// Remove all filter parameters
|
||||||
|
for (const [key] of urlParams.entries()) {
|
||||||
|
if (key.startsWith('filter[')) {
|
||||||
|
urlParams.delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep non-filter parameters
|
||||||
|
const params = {};
|
||||||
|
for (const [key, value] of urlParams.entries()) {
|
||||||
|
if (!key.startsWith('filter[')) {
|
||||||
|
params[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadProducts(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadGenders() {
|
||||||
|
const currentGenderId = new URLSearchParams(window.location.search).get('filter[gender]');
|
||||||
|
|
||||||
|
fetch(`{{ route('product.ajax.genders') }}?current_gender=${currentGenderId || ''}`, {
|
||||||
|
headers: {
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
document.getElementById('genders-list').innerHTML = data.genders;
|
||||||
|
|
||||||
|
// Attach event listeners to newly loaded gender links
|
||||||
|
const genderLinks = document.querySelectorAll('#genders-list a[data-gender-id]');
|
||||||
|
genderLinks.forEach(link => {
|
||||||
|
link.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// Remove active class from all gender links
|
||||||
|
genderLinks.forEach(g => g.classList.remove('active', 'text-primary'));
|
||||||
|
// Add active class to clicked link
|
||||||
|
this.classList.add('active', 'text-primary');
|
||||||
|
|
||||||
|
const genderId = this.getAttribute('data-gender-id');
|
||||||
|
loadProducts({ 'filter[gender]': genderId });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error loading genders:', error);
|
||||||
|
document.getElementById('genders-list').innerHTML = '<li class="nav-item mb-1"><span class="text-danger">Error loading genders</span></li>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadCategories() {
|
||||||
|
const currentCategoryId = new URLSearchParams(window.location.search).get('filter[category]');
|
||||||
|
|
||||||
|
fetch(`{{ route('product.ajax.categories') }}?current_category=${currentCategoryId || ''}`, {
|
||||||
|
headers: {
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
document.getElementById('categories-list').innerHTML = data.categories;
|
||||||
|
|
||||||
|
// Attach event listeners to newly loaded category links
|
||||||
|
const categoryLinks = document.querySelectorAll('#categories-list a[data-category-id]');
|
||||||
|
categoryLinks.forEach(link => {
|
||||||
|
link.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// Remove active class from all category links
|
||||||
|
categoryLinks.forEach(c => c.classList.remove('active', 'text-primary'));
|
||||||
|
// Add active class to clicked link
|
||||||
|
this.classList.add('active', 'text-primary');
|
||||||
|
|
||||||
|
const categoryId = this.getAttribute('data-category-id');
|
||||||
|
loadProducts({ 'filter[category]': categoryId });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error loading categories:', error);
|
||||||
|
document.getElementById('categories-list').innerHTML = '<li class="nav-item mb-1"><span class="text-danger">Error loading categories</span></li>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadProducts(params = {}) {
|
||||||
|
const container = document.getElementById('products-container');
|
||||||
|
const countElement = document.getElementById('product-count');
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
container.innerHTML = '<div class="col-12 text-center py-5"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
||||||
|
countElement.textContent = 'Loading...';
|
||||||
|
|
||||||
|
// Get current URL parameters
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
|
// Add custom parameters
|
||||||
|
Object.keys(params).forEach(key => {
|
||||||
|
if (params[key] !== null) {
|
||||||
|
urlParams.set(key, params[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make AJAX request
|
||||||
|
fetch(`{{ route('product.ajax') }}?${urlParams.toString()}`, {
|
||||||
|
headers: {
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
container.innerHTML = data.products;
|
||||||
|
countElement.textContent = data.count;
|
||||||
|
|
||||||
|
// Update filters section
|
||||||
|
updateFiltersSection(data.filters);
|
||||||
|
|
||||||
|
// Update URL without page reload
|
||||||
|
const newUrl = window.location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '');
|
||||||
|
window.history.pushState({ path: newUrl }, '', newUrl);
|
||||||
|
} else {
|
||||||
|
container.innerHTML = '<div class="col-12 text-center py-5 text-danger">Error loading products</div>';
|
||||||
|
countElement.textContent = '0';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
container.innerHTML = '<div class="col-12 text-center py-5 text-danger">Error loading products</div>';
|
||||||
|
countElement.textContent = '0';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFiltersSection(filters) {
|
||||||
|
const filtersContainer = document.querySelector('.filter-sidebar');
|
||||||
|
const filtersSection = filtersContainer.querySelector('.pb-4.mb-2.mb-xl-3');
|
||||||
|
|
||||||
|
if (Object.keys(filters).length > 0) {
|
||||||
|
// Build filters HTML
|
||||||
|
let filtersHtml = `
|
||||||
|
<div class="pb-4 mb-2 mb-xl-3">
|
||||||
|
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||||
|
<h4 class="h6 mb-0">Filter</h4>
|
||||||
|
<a type="button" href="#"
|
||||||
|
class="btn btn-sm btn-secondary bg-transparent border-0 text-decoration-underline p-0 ms-2 clear-all-filters">
|
||||||
|
Clear all
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-wrap gap-2">
|
||||||
|
`;
|
||||||
|
|
||||||
|
Object.keys(filters).forEach(key => {
|
||||||
|
filtersHtml += `
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary remove-filter"
|
||||||
|
data-filter-key="${key}">
|
||||||
|
<i class="ci-close fs-sm ms-n1 me-1"></i>
|
||||||
|
${filters[key]}
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
filtersHtml += `
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Update or create filters section
|
||||||
|
if (filtersSection) {
|
||||||
|
filtersSection.outerHTML = filtersHtml;
|
||||||
|
} else {
|
||||||
|
filtersContainer.insertAdjacentHTML('afterbegin', filtersHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-attach event listeners for new filter buttons
|
||||||
|
attachFilterEventListeners();
|
||||||
|
} else {
|
||||||
|
// Remove filters section if no filters
|
||||||
|
if (filtersSection) {
|
||||||
|
filtersSection.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachFilterEventListeners() {
|
||||||
|
// Handle filter removal
|
||||||
|
const removeFilterButtons = document.querySelectorAll('.remove-filter');
|
||||||
|
removeFilterButtons.forEach(button => {
|
||||||
|
button.addEventListener('click', function() {
|
||||||
|
const filterKey = this.getAttribute('data-filter-key');
|
||||||
|
removeFilter(filterKey);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle clear all filters
|
||||||
|
const clearAllButton = document.querySelector('.clear-all-filters');
|
||||||
|
if (clearAllButton) {
|
||||||
|
clearAllButton.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
clearAllFilters();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('scripts')
|
@section('scripts')
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,7 @@ Route::post('/locale/switch', [LocaleController::class, 'switch'])->name('locale
|
||||||
Route::get('/', [HomeController::class, 'index'])->name('home');
|
Route::get('/', [HomeController::class, 'index'])->name('home');
|
||||||
|
|
||||||
Route::get('/products',[ProductController::class, 'index'])->name('product.index');
|
Route::get('/products',[ProductController::class, 'index'])->name('product.index');
|
||||||
|
Route::get('/products/ajax',[ProductController::class, 'ajax'])->name('product.ajax');
|
||||||
|
Route::get('/products/ajax/categories',[ProductController::class, 'categories'])->name('product.ajax.categories');
|
||||||
|
Route::get('/products/ajax/genders',[ProductController::class, 'genders'])->name('product.ajax.genders');
|
||||||
Route::get('/product/{slug}',[ProductController::class, 'detail'])->name('product.detail');
|
Route::get('/product/{slug}',[ProductController::class, 'detail'])->name('product.detail');
|
||||||
Loading…
Reference in New Issue