Dashboard: TV station filter tabs nad jobs-list

- Tabi: Vse / FOLX SLOVENIJA / FOLX DE / ONE DE / ZWEI MUSIC / ADRIA / (brez postaje)
- Števec na vsakem tabu = število NEPOTRJENIH jobov (!hidden_after_upload) za to postajo
- Klik na tab = filter samo tisti station, samo nepotrjeni
- 'Vse' = vsi nepotrjeni (kot do zdaj)
- '(brez postaje)' tab se skrije, če ni jobov brez postaje
- Persist v localStorage (reels_jobs_station_filter)
- Iskanje IGNORIRA station filter (vrne tudi naložene + vse postaje)
- Empty state sporočilo prilagojeno glede na izbran filter
This commit is contained in:
Claude 2026-05-03 12:48:31 +00:00
parent 0d72d70f5d
commit 2fcc4b8075

View File

@ -420,6 +420,30 @@
</label>
</div>
</div>
<!-- Filter po TV postaji — pokaže samo še-ne-potrjene (ne-naložene) jobe -->
<div class="station-filter-tabs" id="station-filter-tabs" style="display:flex; flex-wrap:wrap; gap:6px; margin-bottom:12px;">
<button type="button" class="station-filter-tab active" data-station="" style="padding:5px 11px; border:1px solid var(--accent); background:var(--accent); color:#fff; border-radius:4px; cursor:pointer; font-size:12px;">
Vse <span class="cnt" data-cnt-all>0</span>
</button>
<button type="button" class="station-filter-tab" data-station="FOLX SLOVENIJA" style="padding:5px 11px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:12px;">
FOLX SLOVENIJA <span class="cnt" data-cnt="FOLX SLOVENIJA">0</span>
</button>
<button type="button" class="station-filter-tab" data-station="FOLX DE" style="padding:5px 11px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:12px;">
FOLX DE <span class="cnt" data-cnt="FOLX DE">0</span>
</button>
<button type="button" class="station-filter-tab" data-station="ONE DE" style="padding:5px 11px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:12px;">
ONE DE <span class="cnt" data-cnt="ONE DE">0</span>
</button>
<button type="button" class="station-filter-tab" data-station="ZWEI MUSIC" style="padding:5px 11px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:12px;">
ZWEI MUSIC <span class="cnt" data-cnt="ZWEI MUSIC">0</span>
</button>
<button type="button" class="station-filter-tab" data-station="ADRIA" style="padding:5px 11px; border:1px solid #444; background:transparent; color:#ccc; border-radius:4px; cursor:pointer; font-size:12px;">
ADRIA <span class="cnt" data-cnt="ADRIA">0</span>
</button>
<button type="button" class="station-filter-tab" data-station="__none__" style="padding:5px 11px; border:1px solid #444; background:transparent; color:#888; border-radius:4px; cursor:pointer; font-size:12px;" title="Joby brez nastavljene TV postaje">
(brez postaje) <span class="cnt" data-cnt="__none__">0</span>
</button>
</div>
<div class="jobs-list" id="jobs-list">
<div class="empty">Še ni obdelav</div>
</div>
@ -1074,17 +1098,30 @@
const list = $("#jobs-list");
const showUploaded = $("#show-uploaded") && $("#show-uploaded").checked;
const searchQuery = ($("#jobs-search") && $("#jobs-search").value) || "";
// Filtriraj: če iskanje aktivno → ignore hidden_after_upload (iskanje vidi vse)
const stationFilter = (window._stationFilter !== undefined ? window._stationFilter : "");
// 1) Posodobi števce ob tabih — samo ne-potrjeni (!hidden_after_upload) joby
updateStationCounts(data.jobs);
// 2) Filtriraj za prikaz
const visible = data.jobs.filter(j => {
// Iskanje IGNORIRA hidden filter (vrne tudi naložene), TUDI station filter
if (searchQuery.trim()) return jobMatchesSearch(j, searchQuery);
return showUploaded || !j.hidden_after_upload;
// Sicer: skrij potrjene (razen če je showUploaded)
if (!showUploaded && j.hidden_after_upload) return false;
// Station filter: prazen string = "Vse", drugače uskladi
if (stationFilter === "") return true;
if (stationFilter === "__none__") return !j.tv_station;
return (j.tv_station || "") === stationFilter;
});
if (!visible.length) {
list.innerHTML = searchQuery.trim()
? `<div class="empty">Ni zadetkov za "${escapeHtml(searchQuery)}"</div>`
: (showUploaded
? '<div class="empty">Še ni obdelav</div>'
: '<div class="empty">Vse obdelano in naloženo. Klikni "Pokaži tudi že naložene" če želiš popraviti.</div>');
: (stationFilter
? `<div class="empty">Ni nepotrjenih reelov za <b>${escapeHtml(stationFilter === "__none__" ? "(brez postaje)" : stationFilter)}</b>.</div>`
: (showUploaded
? '<div class="empty">Še ni obdelav</div>'
: '<div class="empty">Vse obdelano in naloženo. Klikni "Pokaži tudi že naložene" če želiš popraviti.</div>'));
return;
}
list.innerHTML = "";
@ -1096,6 +1133,30 @@
}
});
}
// Posodobi števce ob station-filter tabih.
// Šteje samo še-ne-potrjene jobe (!hidden_after_upload).
function updateStationCounts(jobs) {
const tabs = $("#station-filter-tabs");
if (!tabs) return;
const pending = jobs.filter(j => !j.hidden_after_upload);
const counts = {};
pending.forEach(j => {
const k = j.tv_station || "__none__";
counts[k] = (counts[k] || 0) + 1;
});
// Vse
const allEl = tabs.querySelector("[data-cnt-all]");
if (allEl) allEl.textContent = pending.length;
// Posamezne postaje
tabs.querySelectorAll("[data-cnt]").forEach(el => {
const key = el.dataset.cnt;
el.textContent = counts[key] || 0;
});
// Skrij/show "(brez postaje)" tab — samo če imamo kakšen brez postaje
const noneTab = tabs.querySelector('[data-station="__none__"]');
if (noneTab) noneTab.style.display = (counts["__none__"] || 0) > 0 ? "" : "none";
}
// Toggle pokaži/skrij že naložene + iskalnik
document.addEventListener("DOMContentLoaded", () => {
@ -1109,6 +1170,38 @@
searchTimer = setTimeout(refreshJobs, 150);
});
}
// Station filter tabs
const stationTabs = $$(".station-filter-tab");
// Restore from localStorage
try {
const saved = localStorage.getItem("reels_jobs_station_filter");
if (saved !== null) window._stationFilter = saved;
} catch (e) {}
// Apply visual active state
stationTabs.forEach(t => {
const isActive = (t.dataset.station || "") === (window._stationFilter || "");
t.classList.toggle("active", isActive);
t.style.borderColor = isActive ? "var(--accent)" : "#444";
t.style.background = isActive ? "var(--accent)" : "transparent";
t.style.color = isActive ? "#fff" : (t.dataset.station === "__none__" ? "#888" : "#ccc");
});
// Click handler
stationTabs.forEach(tab => {
tab.addEventListener("click", () => {
const station = tab.dataset.station || "";
window._stationFilter = station;
try { localStorage.setItem("reels_jobs_station_filter", station); } catch(e) {}
// Vizualno označi
stationTabs.forEach(t => {
const active = t === tab;
t.classList.toggle("active", active);
t.style.borderColor = active ? "var(--accent)" : "#444";
t.style.background = active ? "var(--accent)" : "transparent";
t.style.color = active ? "#fff" : (t.dataset.station === "__none__" ? "#888" : "#ccc");
});
refreshJobs();
});
});
});
function updateJobInList(job) {