Add pagination with 'Näytä lisää' button (24 posts per page)

Shows 24 posts initially, loads 24 more each click. Resets on filter/search change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 15:16:28 +02:00
parent 4285bb0d40
commit 5d09f5b333
2 changed files with 29 additions and 6 deletions

View File

@@ -30,7 +30,7 @@
<section class="controls" id="posts">
<div class="container">
<div class="search-row">
<input type="text" id="search" data-i18n-ph="search_ph" oninput="filterPosts()" />
<input type="text" id="search" data-i18n-ph="search_ph" oninput="visibleCount=POSTS_PER_PAGE;filterPosts()" />
<button class="likes-filter-btn" id="likesFilterBtn" onclick="toggleLikesFilter()">❤️ Tykkäämäni</button>
</div>
<div class="filters" id="categoryFilters"></div>
@@ -44,6 +44,9 @@
<div class="container">
<div class="recipe-grid" id="postGrid"></div>
<p class="no-results" id="noResults" style="display:none;" data-i18n="no_results"></p>
<div id="loadMoreWrap" style="text-align:center;margin:24px 0;display:none">
<button id="loadMoreBtn" onclick="loadMore()" style="padding:10px 32px;font-size:1rem;border:2px solid #c4956a;background:#fff;color:#8b5e3c;border-radius:24px;cursor:pointer;font-weight:600">Näytä lisää</button>
</div>
</div>
</section>

View File

@@ -225,11 +225,15 @@ function shuffleArray(arr) {
return arr;
}
const POSTS_PER_PAGE = 24;
let visibleCount = POSTS_PER_PAGE;
function renderCards() {
const grid = document.getElementById('postGrid');
if (!grid) return;
shuffleArray(APP.posts);
visibleCount = POSTS_PER_PAGE;
grid.innerHTML = APP.posts.map(p => {
const liked = APP.userLikes.includes(p.id);
const likeCount = APP.likes[p.id] || 0;
@@ -269,6 +273,7 @@ let currentSubFilter = 'all';
function setFilter(category, btn) {
currentFilter = category;
currentSubFilter = 'all';
visibleCount = POSTS_PER_PAGE;
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
renderSubFilters();
@@ -277,6 +282,7 @@ function setFilter(category, btn) {
function setSubFilter(sub, btn) {
currentSubFilter = sub;
visibleCount = POSTS_PER_PAGE;
document.querySelectorAll('.sub-filter-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
filterPosts();
@@ -297,7 +303,8 @@ function renderSubFilters() {
function filterPosts() {
const query = (document.getElementById('search')?.value || '').toLowerCase();
const cards = document.querySelectorAll('.recipe-card');
let visible = 0;
let matched = 0;
let shown = 0;
cards.forEach(card => {
const matchesCat = currentFilter === 'all' || card.dataset.category === currentFilter;
const postSubs = (card.dataset.subcategory || '').split(',').filter(Boolean);
@@ -309,12 +316,24 @@ function filterPosts() {
const matchesSearch = !query || title.includes(query) || desc.includes(query) || subLbl.includes(query) || author.includes(query);
const postId = card.querySelector('[data-like-id]')?.dataset.likeId || '';
const matchesLikes = !APP.showOnlyLiked || APP.userLikes.includes(postId);
const show = matchesCat && matchesSub && matchesSearch && matchesLikes;
card.style.display = show ? '' : 'none';
if (show) visible++;
const matchesFilter = matchesCat && matchesSub && matchesSearch && matchesLikes;
if (matchesFilter) {
matched++;
card.style.display = matched <= visibleCount ? '' : 'none';
if (matched <= visibleCount) shown++;
} else {
card.style.display = 'none';
}
});
const noRes = document.getElementById('noResults');
if (noRes) noRes.style.display = visible === 0 ? 'block' : 'none';
if (noRes) noRes.style.display = matched === 0 ? 'block' : 'none';
const wrap = document.getElementById('loadMoreWrap');
if (wrap) wrap.style.display = matched > shown ? '' : 'none';
}
function loadMore() {
visibleCount += POSTS_PER_PAGE;
filterPosts();
}
// ===========================
@@ -930,6 +949,7 @@ async function init() {
renderCategoryFilters();
renderSubFilters();
renderCards();
filterPosts();
// Open post from URL hash (e.g. #resepti/pinaattiletut)
const hash = window.location.hash;