Wiki pagination — 9 cards/page (3 rows), counter X/27, topic filter pills, prev/next
- wikiPerPage = 9 (3 masonry rows × 3 cols), wikiCurrentPage state - wikiFilteredData holds sorted/filtered list; renderWikiPage slices it - Topic filter pills below search bar, rendered from unique topics in data - searchWiki now works with pagination/filters, resets to page 1 - Counter shows '9/27' style, pagination shows Zurück/Weiter with page info - Language toggle re-renders wiki topics + page - New CSS: .wiki-topics, .wiki-topic-filter (pill style), .wiki-footer, .wiki-page-btn
This commit is contained in:
@@ -1054,6 +1054,85 @@ body[data-lang="en"] .hide-de { display: none !important; }
|
||||
.rank-badge.rank-expert { background: #fff3e0; color: #e65100; }
|
||||
.rank-badge.rank-legend { background: #fce4ec; color: #c62828; }
|
||||
|
||||
/* ========================================
|
||||
WIKI TOPICS — filter pills
|
||||
======================================== */
|
||||
.wiki-topics {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin: 12px 0 20px;
|
||||
}
|
||||
.wiki-topic-filter {
|
||||
background: #f0f2f5;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
padding: 5px 12px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #1c1e21;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s, color 0.2s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.wiki-topic-filter:hover {
|
||||
background: #e4e6eb;
|
||||
}
|
||||
.wiki-topic-filter.active {
|
||||
background: #1877f2;
|
||||
color: #fff;
|
||||
}
|
||||
.wiki-filter-count {
|
||||
font-size: 11px;
|
||||
opacity: 0.7;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
WIKI FOOTER — counter + pagination
|
||||
======================================== */
|
||||
.wiki-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
margin-top: 24px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.wiki-counter {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #65676b;
|
||||
}
|
||||
.wiki-pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.wiki-page-btn {
|
||||
background: #f0f2f5;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 6px 14px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #1c1e21;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.wiki-page-btn:hover:not(:disabled) {
|
||||
background: #e4e6eb;
|
||||
}
|
||||
.wiki-page-btn:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: default;
|
||||
}
|
||||
.wiki-page-info {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #65676b;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
WIKI CARDS
|
||||
======================================== */
|
||||
|
||||
@@ -436,12 +436,17 @@
|
||||
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
|
||||
<input type="text" id="wiki-search" class="search-input" placeholder="Wiki durchsuchen..." />
|
||||
</div>
|
||||
<div class="wiki-topics" id="wiki-topics"></div>
|
||||
<div class="wiki-grid" id="wiki-grid">
|
||||
<p class="loading-text">
|
||||
<span class="hide-de">Lade Wiki...</span>
|
||||
<span class="hide-en">Loading wiki...</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="wiki-footer" id="wiki-footer">
|
||||
<div class="wiki-counter" id="wiki-counter"></div>
|
||||
<div class="wiki-pagination" id="wiki-pagination"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
+114
-20
@@ -273,6 +273,10 @@ function setLanguage(lang) {
|
||||
b.classList.toggle('active', b.dataset.lang === lang);
|
||||
});
|
||||
renderCalendar();
|
||||
if (wikiData.length) {
|
||||
renderWikiTopics();
|
||||
renderWikiPage();
|
||||
}
|
||||
}
|
||||
|
||||
function isDE() {
|
||||
@@ -730,6 +734,20 @@ function getTopicColor(topic) {
|
||||
|
||||
// ========================================
|
||||
let wikiData = [];
|
||||
let wikiCurrentPage = 1;
|
||||
let wikiPerPage = 9;
|
||||
let wikiFilteredData = [];
|
||||
let wikiActiveTopic = '';
|
||||
|
||||
// Get unique topics with counts from the full wiki data
|
||||
function getWikiTopics(data) {
|
||||
const map = {};
|
||||
data.forEach(item => {
|
||||
const t = currentLang === 'en' && item.topic_en ? item.topic_en : (item.topic || 'Unknown');
|
||||
map[t] = (map[t] || 0) + 1;
|
||||
});
|
||||
return Object.entries(map).sort();
|
||||
}
|
||||
|
||||
async function loadWiki() {
|
||||
try {
|
||||
@@ -739,17 +757,94 @@ async function loadWiki() {
|
||||
|
||||
if (result.data && Array.isArray(result.data)) {
|
||||
wikiData = result.data;
|
||||
renderWikiCards(wikiData);
|
||||
|
||||
// Wiki count will be loaded from community webhook
|
||||
wikiFilteredData = [...result.data].sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt));
|
||||
wikiCurrentPage = 1;
|
||||
wikiActiveTopic = '';
|
||||
renderWikiTopics();
|
||||
renderWikiPage();
|
||||
} else {
|
||||
document.getElementById('wiki-grid').innerHTML = '<p class="loading-text">' + (isDE() ? 'Keine Wiki-Daten' : 'No wiki data') + '</p>';
|
||||
const c = document.getElementById('wiki-counter'); if (c) c.innerHTML = '';
|
||||
const p = document.getElementById('wiki-pagination'); if (p) p.innerHTML = '';
|
||||
}
|
||||
} catch (error) {
|
||||
document.getElementById('wiki-grid').innerHTML = '<p class="loading-text">' + (isDE() ? 'Fehler beim Laden' : 'Error loading') + '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
function renderWikiTopics() {
|
||||
const container = document.getElementById('wiki-topics');
|
||||
if (!container) return;
|
||||
const topics = getWikiTopics(wikiData);
|
||||
let html = '<button class="wiki-topic-filter' + (wikiActiveTopic === '' ? ' active' : '') + '" onclick="filterWikiByTopic(\'\')">' +
|
||||
(isDE() ? 'Alle' : 'All') + ' <span class="wiki-filter-count">' + wikiData.length + '</span></button>';
|
||||
topics.forEach(([topic, count]) => {
|
||||
const esc = escapeHtml(topic).replace(/'/g, "\\'");
|
||||
html += '<button class="wiki-topic-filter' + (topic === wikiActiveTopic ? ' active' : '') + '" onclick="filterWikiByTopic(\'' + esc + '\')">' +
|
||||
escapeHtml(topic) + ' <span class="wiki-filter-count">' + count + '</span></button>';
|
||||
});
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
function filterWikiByTopic(topic) {
|
||||
wikiActiveTopic = topic;
|
||||
if (!topic) {
|
||||
wikiFilteredData = [...wikiData].sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt));
|
||||
} else {
|
||||
wikiFilteredData = [...wikiData].filter(item => {
|
||||
const t = currentLang === 'en' && item.topic_en ? item.topic_en : (item.topic || '');
|
||||
return t === topic;
|
||||
}).sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt));
|
||||
}
|
||||
wikiCurrentPage = 1;
|
||||
renderWikiTopics();
|
||||
renderWikiPage();
|
||||
}
|
||||
|
||||
function renderWikiPage() {
|
||||
const total = wikiFilteredData.length;
|
||||
const totalPages = Math.max(1, Math.ceil(total / wikiPerPage));
|
||||
if (wikiCurrentPage > totalPages) wikiCurrentPage = totalPages;
|
||||
const start = (wikiCurrentPage - 1) * wikiPerPage;
|
||||
const pageData = wikiFilteredData.slice(start, start + wikiPerPage);
|
||||
renderWikiCards(pageData);
|
||||
renderWikiCounter(start, total);
|
||||
renderWikiPagination(totalPages);
|
||||
}
|
||||
|
||||
function renderWikiCounter(start, total) {
|
||||
const el = document.getElementById('wiki-counter');
|
||||
if (!el) return;
|
||||
if (total === 0 || start >= total) { el.innerHTML = ''; return; }
|
||||
const shown = Math.min(wikiPerPage, total - start);
|
||||
el.textContent = start + shown + '/' + total;
|
||||
}
|
||||
|
||||
function renderWikiPagination(totalPages) {
|
||||
const el = document.getElementById('wiki-pagination');
|
||||
if (!el) return;
|
||||
if (totalPages <= 1) { el.innerHTML = ''; return; }
|
||||
el.innerHTML =
|
||||
'<button class="wiki-page-btn" onclick="wikiGoPage(' + (wikiCurrentPage - 1) + ')"' + (wikiCurrentPage <= 1 ? ' disabled' : '') + '>' +
|
||||
'<span class="hide-de">Zurück</span><span class="hide-en">Previous</span></button>' +
|
||||
'<span class="wiki-page-info">' + wikiCurrentPage + '/' + totalPages + '</span>' +
|
||||
'<button class="wiki-page-btn" onclick="wikiGoPage(' + (wikiCurrentPage + 1) + ')"' + (wikiCurrentPage >= totalPages ? ' disabled' : '') + '>' +
|
||||
'<span class="hide-de">Weiter</span><span class="hide-en">Next</span></button>';
|
||||
}
|
||||
|
||||
function wikiGoPage(page) {
|
||||
const total = wikiFilteredData.length;
|
||||
const totalPages = Math.max(1, Math.ceil(total / wikiPerPage));
|
||||
if (page < 1 || page > totalPages) return;
|
||||
wikiCurrentPage = page;
|
||||
const start = (wikiCurrentPage - 1) * wikiPerPage;
|
||||
renderWikiCards(wikiFilteredData.slice(start, start + wikiPerPage));
|
||||
renderWikiCounter(start, total);
|
||||
renderWikiPagination(totalPages);
|
||||
const section = document.querySelector('#wiki');
|
||||
if (section) section.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
|
||||
function renderWikiCards(data) {
|
||||
const grid = document.getElementById('wiki-grid');
|
||||
grid.innerHTML = '';
|
||||
@@ -759,9 +854,7 @@ function renderWikiCards(data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sorted = [...data].sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt));
|
||||
|
||||
sorted.forEach((item, idx) => {
|
||||
data.forEach((item, idx) => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'wiki-card-new stagger-' + (idx % 4 + 1);
|
||||
card.setAttribute('role', 'button');
|
||||
@@ -769,7 +862,6 @@ function renderWikiCards(data) {
|
||||
|
||||
const topic = currentLang === 'en' && item.topic_en ? item.topic_en : (item.topic || 'Unknown');
|
||||
const topicColor = getTopicColor(topic);
|
||||
// Feed topic accent into CSS custom properties (top bar + hover border)
|
||||
card.style.setProperty('--topic-accent', topicColor.border);
|
||||
|
||||
const subtopic = currentLang === 'en' && item.subtopic_en ? item.subtopic_en : (item.subtopic || '');
|
||||
@@ -839,20 +931,22 @@ function openWikiModalSingle(item) {
|
||||
}
|
||||
|
||||
function searchWiki(term) {
|
||||
if (!term.trim()) {
|
||||
renderWikiCards(wikiData);
|
||||
return;
|
||||
const t = term.toLowerCase().trim();
|
||||
if (!t) {
|
||||
wikiActiveTopic = '';
|
||||
wikiFilteredData = [...wikiData].sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt));
|
||||
} else {
|
||||
wikiActiveTopic = '';
|
||||
wikiFilteredData = wikiData.filter(item => {
|
||||
const text = ((item.topic_en && currentLang === 'en') ? item.topic_en : (item.topic || '')) + ' ' +
|
||||
((item.subtopic_en && currentLang === 'en') ? item.subtopic_en : (item.subtopic || '')) + ' ' +
|
||||
((item.wiki_en && currentLang === 'en') ? item.wiki_en : (item.wiki || ''));
|
||||
return text.toLowerCase().includes(t);
|
||||
}).sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt));
|
||||
}
|
||||
|
||||
const t = term.toLowerCase();
|
||||
const filtered = wikiData.filter(item => {
|
||||
const topic = ((item.topic_en && currentLang === 'en') ? item.topic_en : (item.topic || '')) +
|
||||
' ' + ((item.subtopic_en && currentLang === 'en') ? item.subtopic_en : (item.subtopic || '')) +
|
||||
' ' + ((item.wiki_en && currentLang === 'en') ? item.wiki_en : (item.wiki || ''));
|
||||
return topic.toLowerCase().includes(t);
|
||||
});
|
||||
|
||||
renderWikiCards(filtered);
|
||||
renderWikiTopics();
|
||||
wikiCurrentPage = 1;
|
||||
renderWikiPage();
|
||||
}
|
||||
|
||||
function getTopicColor(topic) {
|
||||
|
||||
Reference in New Issue
Block a user