This commit is contained in:
2026-06-06 09:18:00 -04:00
parent c92478ebe5
commit 688febf17f

View File

@@ -1,8 +1,156 @@
/* assoc_profile — v0.1.0 */
/* assoc_profile — v0.2.0
Client-side search, filter, pagination, and bulk select for the manage index.
No dependencies beyond Bootstrap 5 (already loaded by Hubzilla). */
(function () {
'use strict';
function init() {
// TODO: progressive enhancement for profile edit form if needed
// ----------------------------------------------------------------
// MANAGE INDEX — search, filter, paginate, bulk select
// ----------------------------------------------------------------
var PAGE_SIZE = 25;
function initManageIndex() {
var table = document.getElementById('assoc-manage-table');
if (!table) return;
var rows = Array.from(table.querySelectorAll('tbody tr[data-slug]'));
var searchInput = document.getElementById('assoc-search');
var filterCounty = document.getElementById('assoc-filter-county');
var filterType = document.getElementById('assoc-filter-type');
var filterStatus = document.getElementById('assoc-filter-status');
var pageInfo = document.getElementById('assoc-page-info');
var prevBtn = document.getElementById('assoc-page-prev');
var nextBtn = document.getElementById('assoc-page-next');
var selectAll = document.getElementById('assoc-select-all');
var bulkBar = document.getElementById('assoc-bulk-bar');
var bulkCount = document.getElementById('assoc-bulk-count');
var exportBtn = document.getElementById('assoc-export-selected');
var currentPage = 1;
var filtered = rows.slice();
function getRowText(row) {
return (row.dataset.slug + ' ' +
row.dataset.name + ' ' +
(row.dataset.county || '')).toLowerCase();
}
document.addEventListener('DOMContentLoaded', init);
function applyFilters() {
var q = searchInput ? searchInput.value.toLowerCase().trim() : '';
var county = filterCounty ? filterCounty.value : '';
var type = filterType ? filterType.value : '';
var status = filterStatus ? filterStatus.value : '';
filtered = rows.filter(function (row) {
if (q && getRowText(row).indexOf(q) === -1) return false;
if (county && row.dataset.county !== county) return false;
if (type && row.dataset.type !== type) return false;
if (status && row.dataset.status !== status) return false;
return true;
});
currentPage = 1;
render();
}
function render() {
var total = filtered.length;
var pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
currentPage = Math.min(currentPage, pages);
var start = (currentPage - 1) * PAGE_SIZE;
var end = Math.min(start + PAGE_SIZE, total);
rows.forEach(function (row) { row.style.display = 'none'; });
filtered.slice(start, end).forEach(function (row) { row.style.display = ''; });
if (pageInfo) {
pageInfo.textContent = total === 0
? 'No associations found'
: 'Showing ' + (start + 1) + '' + end + ' of ' + total;
}
if (prevBtn) prevBtn.disabled = currentPage <= 1;
if (nextBtn) nextBtn.disabled = currentPage >= pages;
}
function updateBulkBar() {
if (!bulkBar) return;
var checked = table.querySelectorAll('tbody input[name="assoc_select[]"]:checked');
var n = checked.length;
bulkBar.style.display = n > 0 ? 'flex' : 'none';
if (bulkCount) bulkCount.textContent = n + ' selected';
}
// Event wiring
if (searchInput) searchInput.addEventListener('input', applyFilters);
if (filterCounty) filterCounty.addEventListener('change', applyFilters);
if (filterType) filterType.addEventListener('change', applyFilters);
if (filterStatus) filterStatus.addEventListener('change', applyFilters);
if (prevBtn) prevBtn.addEventListener('click', function () {
if (currentPage > 1) { currentPage--; render(); }
});
if (nextBtn) nextBtn.addEventListener('click', function () {
var pages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
if (currentPage < pages) { currentPage++; render(); }
});
if (selectAll) {
selectAll.addEventListener('change', function () {
var visible = table.querySelectorAll('tbody tr[data-slug]:not([style*="none"]) input[name="assoc_select[]"]');
visible.forEach(function (cb) { cb.checked = selectAll.checked; });
updateBulkBar();
});
}
table.addEventListener('change', function (e) {
if (e.target.name === 'assoc_select[]') updateBulkBar();
});
if (exportBtn) {
exportBtn.addEventListener('click', function () {
var checked = Array.from(table.querySelectorAll('tbody input[name="assoc_select[]"]:checked'));
var slugs = checked.map(function (cb) { return cb.value; });
if (!slugs.length) return;
var form = document.getElementById('assoc-export-form');
if (!form) return;
document.getElementById('assoc-export-slugs').value = slugs.join(',');
form.submit();
});
}
render();
}
// ----------------------------------------------------------------
// DIFF VIEW — confirm/skip per entry
// ----------------------------------------------------------------
function initDiffView() {
var container = document.getElementById('assoc-diff-container');
if (!container) return;
container.addEventListener('change', function (e) {
if (e.target.name === 'diff_action[]') {
var entry = e.target.closest('.assoc-diff-entry');
if (!entry) return;
if (e.target.value === 'skip') {
entry.style.opacity = '0.45';
} else {
entry.style.opacity = '1';
}
}
});
}
// ----------------------------------------------------------------
// INIT
// ----------------------------------------------------------------
document.addEventListener('DOMContentLoaded', function () {
initManageIndex();
initDiffView();
});
})();