From 345f95297030646af4fd7b716f7f4f48169478c4 Mon Sep 17 00:00:00 2001 From: mandalore Date: Fri, 4 Sep 2026 17:10:20 -0500 Subject: [PATCH] Add a Circuit filter to the filter bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Buttons are generated from CONFIG.circuits (not hand-written in index.html), so adding a circuit to the config still only takes one line — its filter button appears automatically. Uses accent color to match the circuit badges on the cards, same active/dimmed styling as Format/Scope. An event matches the circuit filter if it belongs to any active circuit (OR within the group), not all of them, since an event can legitimately carry more than one circuit tag. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01SBzcNkW7JcYipnAX6HfgmK --- sites/events/index.html | 2 ++ sites/events/src/main.js | 35 ++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/sites/events/index.html b/sites/events/index.html index fbdcc7e..c4590b7 100644 --- a/sites/events/index.html +++ b/sites/events/index.html @@ -26,6 +26,8 @@ Scope + Circuit + diff --git a/sites/events/src/main.js b/sites/events/src/main.js index cc03d97..9cff820 100644 --- a/sites/events/src/main.js +++ b/sites/events/src/main.js @@ -215,25 +215,42 @@ function scopeOf(ev) { /* ---- Filters ---- */ const activeFormats = new Set(["Singles", "Team Event"]); const activeScopes = new Set(["RTT", "GT"]); +const activeCircuits = new Set(CONFIG.circuits.map(c => c.id)); -function passesFilter(ev) { +// An event passes the circuit filter if it belongs to at least one +// active circuit — it's an OR within the group, same as Format/Scope, +// not "must match every circuit it happens to also belong to". +function passesFilter(ev, circuits) { const scope = scopeOf(ev); - return activeFormats.has(formatOf(ev)) && (scope === null || activeScopes.has(scope)); + return activeFormats.has(formatOf(ev)) + && (scope === null || activeScopes.has(scope)) + && circuits.some(c => activeCircuits.has(c.id)); } // Filter buttons use the same color as the badge they control (warning -// for Format, info for Scope) when active, so it's obvious at a glance -// which is which — and switch to a dimmed outline when off, since -// btn-outline alone reads too similarly to its own active state in dark -// mode to tell the two apart at a glance. -const FILTER_GROUP_COLOR = { format: "btn-warning", scope: "btn-info" }; +// for Format, info for Scope, accent for Circuit — matching the badge +// colors on the cards) when active, so it's obvious at a glance which is +// which — and switch to a dimmed outline when off, since btn-outline +// alone reads too similarly to its own active state in dark mode to +// tell the two apart at a glance. +const FILTER_GROUP_COLOR = { format: "btn-warning", scope: "btn-info", circuit: "btn-accent" }; +const FILTER_SET = { format: activeFormats, scope: activeScopes, circuit: activeCircuits }; + +// Circuit buttons are generated from CONFIG rather than hand-written in +// index.html, so adding a circuit there is still a one-line change. +function renderCircuitFilterButtons() { + $("circuit-filters").innerHTML = CONFIG.circuits.map(c => + `` + ).join(""); +} function setupFilters() { + renderCircuitFilterButtons(); document.querySelectorAll("#filters button[data-filter-group]").forEach(btn => { const group = btn.dataset.filterGroup; const onClass = FILTER_GROUP_COLOR[group]; btn.addEventListener("click", () => { - const set = group === "format" ? activeFormats : activeScopes; + const set = FILTER_SET[group]; const nowActive = !btn.classList.contains(onClass); btn.classList.toggle(onClass, nowActive); btn.classList.toggle("btn-outline", !nowActive); @@ -297,7 +314,7 @@ let allResults = []; function renderEvents() { const merged = mergeEvents(allResults); - const filtered = merged.filter(({ event }) => passesFilter(event)); + const filtered = merged.filter(({ event, circuits }) => passesFilter(event, circuits)); const failed = allResults.filter(r => r.error).map(r => r.circuit.name); const errorBanner = failed.length