ldc-groupe/resources/views/components/front/posts/posts-index.blade.php

250 lines
11 KiB
PHP

@php
$wrapperId = 'wrapper-' . uniqid();
@endphp
@if (isset($postContainer))
<div id="{{ $wrapperId }}" data-current-locale="{{ app()->getLocale() }}" @class([
'filter-posts',
$postContainer['class'] ?? null,
])>
<div @class([
'filter fw',
$postContainer['secondaryClass'] ?? null
])>
<div class="filter__wrapper wrapper">
<div class="filter-menu">
<div id="filters" class="filter__select-wrap filter-select-wrap"></div>
<div class="filter-results-num">
{{ ucfirst(__('front.news.results')) }} :
<span class="filter-results-num__wrap">
<span class="filter-results-num__wrap">
<span id="results" class="filter-results-num__current"></span>
{{ __('front.news.on_document_count') }}
<span id="all-results" class="filter-results-num__total"></span>
</span>
</span>
</div>
</div>
<div class="active-filters">
<div id="selected-filters" class="active-filters__list"></div>
<div class="active-filters__clear-wrap">
<div class="active-filters__item active-filters__item_clear">
<a class="active-filters__item-remove" data-category="{{ $postContainer['category'] }}" data-param="clear-all"
title="{{ ucfirst(__('front.buttons.clear_filters')) }}">✖</a>
{{ ucfirst(__('front.buttons.clear_filters')) }}
</div>
</div>
</div>
</div>
</div>
<div @class([
'posts-list fw',
$postContainer['tertiaryClass'] ?? null
])>
<div class="posts-list__wrapper wrapper">
<div @class([
'list-items',
'posts-container' => $postContainer['slug'] === "news",
'list-items_doc' => $postContainer['slug'] === "docs",
])>
<div id="loader" class="lds-ellipsis hidden"><div></div><div></div><div></div><div></div></div>
<div id="section" class="ajax-load-more-wrap infinite fading-circles alm-0 alm-is-loaded">
<div id="posts" class="alm-listing alm-ajax wrapper" data-slug="{{ $postContainer['slug'] }}" data-category="{{ $postContainer['category'] }}"></div>
<div class="alm-btn-wrap">
<button id="load-more" class="alm-load-more-btn more btn" data-page="1" type="button">{{ $postContainer['load_more'] }}</button>
</div>
</div>
</div>
</div>
</div>
</div>
@push('scripts')
<script nonce="{{ $nonce }}">
(function() {
const wrapper = document.getElementById('{{ $wrapperId }}');
const currentLocale = wrapper.dataset.currentLocale;
const postsContainer = wrapper.querySelector('#posts');
const filtersContainer = wrapper.querySelector('#filters');
const nbResults = wrapper.querySelector('#results');
const allResults = wrapper.querySelector('#all-results');
const loadMoreBtn = wrapper.querySelector('#load-more');
const sFiltersContainer = wrapper.querySelector('#selected-filters');
const loader = wrapper.querySelector("#loader");
const section = wrapper.querySelector("#section");
const tblFilters = {};
let hasLoaded = false;
function isLoading(value = false) {
if (value) {
loader.classList.remove('hidden');
section.classList.add('hidden');
} else {
loader.classList.add('hidden');
section.classList.remove('hidden');
}
}
function ajaxLoadPosts(clear = false, filters = {}) {
const currentFilters = new URLSearchParams(window.location.search).toString();
const nextPage = clear ? 1 : parseInt(loadMoreBtn.dataset.page);
const { slug, category } = postsContainer.dataset;
let endpoints = null;
isLoading(true);
if (slug === "news") {
endpoint = "news";
} else if (slug === "docs") {
endpoint = "documents";
}
if (!endpoint) return;
fetch(`/posts/load/${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
},
body: JSON.stringify({
page: nextPage,
category: category,
filters: filters,
locale: currentLocale
})
})
.then(response => response.json())
.then(data => updatePosts(data, clear))
.finally(function () {
isLoading(false);
});
}
function updatePosts(data, clear) {
const pagination = data.pagination;
if (clear) {
postsContainer.innerHTML = data.news;
} else {
postsContainer.insertAdjacentHTML('beforeend', data.news);
}
sFiltersContainer.innerHTML = data.selectedFilters;
filtersContainer.innerHTML = data.filters;
nbResults.innerHTML = postsContainer.childElementCount ?? 0;
allResults.innerHTML = pagination.total ?? 0;
if (pagination.hasMore) {
loadMoreBtn.style.visibility = 'visible';
loadMoreBtn.dataset.page = pagination.currentPage + 1;
} else {
loadMoreBtn.style.visibility = 'hidden';
}
initFilters();
initSelectedFilters();
}
document.addEventListener('scroll', function () {
if (hasLoaded) return;
const wrapperPos = wrapper.getBoundingClientRect();
const isVisible = wrapperPos.top < window.innerHeight * 1.5;
if (isVisible) {
hasLoaded = true;
ajaxLoadPosts();
}
});
loadMoreBtn.addEventListener('click', function() {
loadMoreBtn.classList.add('loading');
loadMoreBtn.disabled = true;
setTimeout(() => {
ajaxLoadPosts();
loadMoreBtn.classList.remove('loading');
loadMoreBtn.disabled = false;
}, 1000);
});
function initFilters() {
const filters = filtersContainer.querySelectorAll('.filter-select');
filters.forEach(filter => {
const filterName = filter.dataset.name;
filter.querySelectorAll('li a.tax-filter').forEach(link => {
const value = link.dataset.value;
const category = link.dataset.category;
if (!tblFilters[category]) {
tblFilters[category] = {
tags: [],
years: [],
order: null
};
}
const values = tblFilters?.[category]?.[filterName] ?? [];
if (values.includes(value)) {
link.classList.add('disabled');
} else {
link.classList.remove('disabled');
}
link.addEventListener('click', function(e) {
e.preventDefault();
const state = tblFilters[category];
if (filterName === 'order') {
state.order = value;
this.classList.add('disabled');
} else {
if (!state[filterName].includes(value)) {
state[filterName].push(value);
this.classList.add('disabled');
}
}
ajaxLoadPosts(true, state);
});
});
});
}
function initSelectedFilters() {
const items = wrapper.querySelectorAll('.active-filters__item-remove');
items.forEach(item => {
item.addEventListener('click', function (e) {
e.preventDefault();
const category = item.dataset.category;
const filterName = item.dataset.param;
const value = item.dataset.value;
if (!category || !tblFilters[category]) return;
if (filterName === 'clear-all') {
Object.keys(tblFilters[category]).forEach(key => {
tblFilters[category][key] = Array.isArray(tblFilters[category][key]) ? [] : null;
});
} else if (filterName && value) {
const tblItem = tblFilters[category][filterName];
if (Array.isArray(tblItem)) {
tblFilters[category][filterName] = tblItem.filter(v => v !== value);
} else if (tblItem === value) {
tblFilters[category][filterName] = null;
}
}
ajaxLoadPosts(true, tblFilters[category]);
});
});
}
})();
</script>
@endpush
@endif