Toggle days filter via icon and persist filter value

This commit is contained in:
2026-02-23 21:48:00 +01:00
parent 85f9de74bf
commit 4291b56fd9
3 changed files with 143 additions and 3 deletions

View File

@@ -1569,9 +1569,16 @@
<thead>
<tr>
<th>
<div class="bookmark-subpage__th-stack">
<button type="button" class="bookmark-subpage__sort" data-trade-sort="tage_bis_start">Tage bis Start</button>
<input type="text" id="tradeFairDaysFilterInput" class="bookmark-subpage__column-filter" placeholder=">0">
<div class="bookmark-subpage__th-stack" id="tradeFairDaysFilterContainer">
<div class="bookmark-subpage__th-controls">
<button type="button" class="bookmark-subpage__sort" data-trade-sort="tage_bis_start">Tage bis Start</button>
<button type="button" id="tradeFairDaysFilterToggle" class="bookmark-subpage__filter-toggle" aria-label="Filter fuer Tage bis Start umschalten" aria-expanded="false" title="Tage bis Start filtern">
<svg viewBox="0 0 20 20" aria-hidden="true" focusable="false">
<path d="M3 4.5C3 4.224 3.224 4 3.5 4h13c.276 0 .5.224.5.5 0 .118-.042.233-.117.323L12 10.409V15a.5.5 0 0 1-.224.416l-3 2A.5.5 0 0 1 8 17v-6.591L3.117 4.823A.5.5 0 0 1 3 4.5z"/>
</svg>
</button>
</div>
<input type="text" id="tradeFairDaysFilterInput" class="bookmark-subpage__column-filter" placeholder=">0" autocomplete="off" spellcheck="false">
</div>
</th>
<th><button type="button" class="bookmark-subpage__sort" data-trade-sort="rang">Rang</button></th>

View File

@@ -2045,6 +2045,44 @@ h1 {
gap: 5px;
}
.bookmark-subpage__th-controls {
display: inline-flex;
align-items: center;
gap: 6px;
}
.bookmark-subpage__filter-toggle {
width: 22px;
height: 22px;
border: 1px solid #cbd5e1;
border-radius: 4px;
background: #fff;
color: #475569;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
cursor: pointer;
}
.bookmark-subpage__filter-toggle svg {
width: 13px;
height: 13px;
fill: currentColor;
}
.bookmark-subpage__filter-toggle:hover {
color: #1f2937;
border-color: #94a3b8;
}
.bookmark-subpage__filter-toggle.is-open,
.bookmark-subpage__filter-toggle.is-active {
color: #0f4bb8;
border-color: #60a5fa;
background: #eff6ff;
}
.bookmark-subpage__column-filter {
width: 84px;
max-width: 100%;
@@ -2054,6 +2092,11 @@ h1 {
color: #111827;
font-size: 11px;
padding: 2px 6px;
display: none;
}
.bookmark-subpage__th-stack.is-filter-open .bookmark-subpage__column-filter {
display: block;
}
.bookmark-subpage__column-filter:focus {

View File

@@ -1,6 +1,8 @@
(function initTradeFairsSubpage() {
const tableBody = document.getElementById('tradeFairTableBody');
const searchInput = document.getElementById('tradeFairSearchInput');
const daysFilterContainer = document.getElementById('tradeFairDaysFilterContainer');
const daysFilterToggle = document.getElementById('tradeFairDaysFilterToggle');
const daysFilterInput = document.getElementById('tradeFairDaysFilterInput');
const meta = document.getElementById('tradeFairMeta');
const columnSettingsBtn = document.getElementById('tradeFairColumnSettingsBtn');
@@ -17,6 +19,7 @@
const COLUMN_ORDER_STATE_KEY = 'fb_trade_fairs_columns_v1';
const COLUMN_VISIBILITY_STATE_KEY = 'fb_trade_fairs_column_visibility_v1';
const LAST_OPEN_STATE_KEY = 'fb_trade_fairs_last_open_v1';
const DAYS_FILTER_STATE_KEY = 'fb_trade_fairs_days_filter_v1';
const DEFAULT_COLUMN_ORDER = [
'tage_bis_start',
'rang',
@@ -721,6 +724,7 @@
let sortDirection = 'asc';
let searchTerm = '';
let daysFilterTerm = '';
let isDaysFilterOpen = false;
let draggedColumnKey = null;
let lastOpenedByTradeFair = {};
let columnVisibility = Object.fromEntries(DEFAULT_COLUMN_ORDER.map((key) => [key, true]));
@@ -1365,6 +1369,51 @@
return `Als Bookmark-Suche oeffnen (3 Tabs)\\nZuletzt geoeffnet: ${suffix}`;
}
function loadDaysFilterState() {
try {
const raw = localStorage.getItem(DAYS_FILTER_STATE_KEY);
if (typeof raw !== 'string') {
return '';
}
return raw.trim();
} catch (_error) {
return '';
}
}
function persistDaysFilterState() {
try {
localStorage.setItem(DAYS_FILTER_STATE_KEY, daysFilterTerm);
} catch (_error) {
// ignore
}
}
function updateDaysFilterToggleState() {
if (!daysFilterToggle) {
return;
}
daysFilterToggle.classList.toggle('is-active', Boolean(daysFilterTerm));
}
function setDaysFilterOpen(nextOpen, options = {}) {
isDaysFilterOpen = Boolean(nextOpen);
if (daysFilterContainer) {
daysFilterContainer.classList.toggle('is-filter-open', isDaysFilterOpen);
}
if (daysFilterToggle) {
daysFilterToggle.classList.toggle('is-open', isDaysFilterOpen);
daysFilterToggle.setAttribute('aria-expanded', isDaysFilterOpen ? 'true' : 'false');
}
if (options.focus && isDaysFilterOpen && daysFilterInput) {
daysFilterInput.focus();
daysFilterInput.select();
}
}
function loadSortState() {
try {
const raw = localStorage.getItem(SORT_STATE_KEY);
@@ -1727,13 +1776,54 @@
render();
});
if (daysFilterToggle) {
daysFilterToggle.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
setDaysFilterOpen(!isDaysFilterOpen, { focus: true });
});
}
if (daysFilterInput) {
daysFilterInput.addEventListener('input', () => {
daysFilterTerm = daysFilterInput.value.trim();
persistDaysFilterState();
updateDaysFilterToggleState();
render();
});
daysFilterInput.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
setDaysFilterOpen(false);
if (daysFilterToggle) {
daysFilterToggle.focus();
}
}
});
}
if (daysFilterContainer) {
document.addEventListener('click', (event) => {
if (!isDaysFilterOpen) {
return;
}
const target = event.target;
if (!(target instanceof Node)) {
return;
}
if (!daysFilterContainer.contains(target)) {
setDaysFilterOpen(false);
}
});
}
daysFilterTerm = loadDaysFilterState();
if (daysFilterInput) {
daysFilterInput.value = daysFilterTerm;
}
updateDaysFilterToggleState();
setDaysFilterOpen(false);
lastOpenedByTradeFair = loadLastOpenedState();
loadColumnOrder();
loadColumnVisibility();