Files
kane-diagnostics/hubzilla/addon/scn01/view/js/scn01.js
2026-06-13 10:36:25 -04:00

184 lines
5.9 KiB
JavaScript

/* scn01 — Scenarios — v0.4.0 */
(function () {
'use strict';
var MAX_PINNED = 3;
function init() {
var dataEl = document.getElementById('scn01-data');
if (!dataEl) return;
var data;
try {
data = JSON.parse(dataEl.textContent);
} catch (e) {
return;
}
var scenarios = data.scenarios || [];
if (!scenarios.length) return;
var cardEl = document.getElementById('scn01-card');
var pinnedEl = document.getElementById('scn01-pinned');
var prevBtn = document.getElementById('scn01-prev');
var nextBtn = document.getElementById('scn01-next');
var fieldsEl = document.getElementById('scn01-pinned-fields');
var categoryEl = document.getElementById('scn01-category');
var index = 0;
var pinned = []; // array of scenario ids, in pin order
var visible = scenarios; // current filtered list
function findScenario(id) {
for (var i = 0; i < scenarios.length; i++) {
if (scenarios[i].id === id) return scenarios[i];
}
return null;
}
function populateCategories() {
if (!categoryEl) return;
var seen = {};
var categories = [];
scenarios.forEach(function (s) {
if (!seen[s.category]) {
seen[s.category] = true;
categories.push(s.category);
}
});
categories.sort();
categories.forEach(function (cat) {
var opt = document.createElement('option');
opt.value = cat;
opt.textContent = cat;
categoryEl.appendChild(opt);
});
categoryEl.addEventListener('change', function () {
applyFilter(categoryEl.value);
});
}
function applyFilter(category) {
visible = category
? scenarios.filter(function (s) { return s.category === category; })
: scenarios;
index = 0;
renderCard();
}
function renderCard() {
if (!cardEl) return;
if (!visible.length) {
cardEl.innerHTML = '<p class="text-muted mb-0">No scenarios in this category.</p>';
return;
}
var s = visible[index];
var isPinned = pinned.indexOf(s.id) !== -1;
var atMax = pinned.length >= MAX_PINNED && !isPinned;
cardEl.innerHTML = '';
var category = document.createElement('div');
category.className = 'scn01-category';
category.textContent = s.category;
cardEl.appendChild(category);
var text = document.createElement('p');
text.className = 'scn01-text';
text.textContent = s.text;
cardEl.appendChild(text);
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'btn btn-sm ' + (isPinned ? 'btn-secondary' : 'btn-outline-primary');
btn.textContent = isPinned ? 'Selected — click to remove' : 'This is similar to my situation';
btn.disabled = atMax;
btn.addEventListener('click', function () {
togglePin(s.id);
});
cardEl.appendChild(btn);
var counter = document.createElement('div');
counter.className = 'scn01-counter small text-muted';
counter.textContent = (index + 1) + ' / ' + visible.length;
cardEl.appendChild(counter);
}
function renderPinned() {
if (!pinnedEl) return;
pinnedEl.innerHTML = '';
if (!pinned.length) {
pinnedEl.style.display = 'none';
return;
}
pinnedEl.style.display = 'block';
var label = document.createElement('div');
label.className = 'scn01-pinned-label small text-muted';
label.textContent = 'Selected (' + pinned.length + '/' + MAX_PINNED + '):';
pinnedEl.appendChild(label);
pinned.forEach(function (id) {
var s = findScenario(id);
if (!s) return;
var chip = document.createElement('span');
chip.className = 'scn01-pin-chip';
chip.textContent = s.category;
chip.title = s.text;
chip.addEventListener('click', function () {
togglePin(id);
});
pinnedEl.appendChild(chip);
});
}
function renderFields() {
if (!fieldsEl) return;
fieldsEl.innerHTML = '';
pinned.forEach(function (id) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'pinned_scenario_ids[]';
input.value = id;
fieldsEl.appendChild(input);
});
}
function togglePin(id) {
var pos = pinned.indexOf(id);
if (pos !== -1) {
pinned.splice(pos, 1);
} else if (pinned.length < MAX_PINNED) {
pinned.push(id);
}
renderPinned();
renderFields();
renderCard();
}
if (prevBtn) {
prevBtn.addEventListener('click', function () {
index = (index - 1 + visible.length) % visible.length;
renderCard();
});
}
if (nextBtn) {
nextBtn.addEventListener('click', function () {
index = (index + 1) % visible.length;
renderCard();
});
}
populateCategories();
renderCard();
renderPinned();
renderFields();
}
document.addEventListener('DOMContentLoaded', init);
})();