diff --git a/admin.html b/admin.html index abc4080..e484b25 100644 --- a/admin.html +++ b/admin.html @@ -332,6 +332,10 @@
Подписки
Все выданные подписки
+
+
+
+
ПользовательСерверТарифВыданаИстекаетСтатус
@@ -969,6 +973,16 @@ function initDropdowns() { const countryOptions = COUNTRIES.map(([code, name]) => ({ value: code, label: `${flagEmoji(code)} ${name}`, })); + DD.subsStatusFilter = createDropdown("subs-status-filter", { + options: [ + { value: "all", label: "Все статусы" }, + { value: "active", label: "Активные" }, + { value: "held", label: "На паузе" }, + { value: "expired", label: "Истекшие/отозванные" }, + ], + value: "all", placeholder: "Статус", + onChange: () => renderFilteredSubs(), + }); DD.ngCountry = createDropdown("ng-country", { options: countryOptions, placeholder: "Страна", searchable: true, onChange: (code) => { @@ -1413,8 +1427,9 @@ async function loadDashboard() { `).join("") : '
Пока нет подписок
'; } -async function loadSubscriptions() { - const subs = await api("/admin/api/subscriptions"); +let allSubs = []; + +function renderSubsTable(subs) { const body = document.getElementById("subs-body"); body.innerHTML = subs.length ? subs.map((s, i) => ` ${s.username ? "@" + esc(s.username) : "tg" + s.tg_id}${esc(s.node_label)}${esc(s.plan_label)} @@ -1429,6 +1444,31 @@ async function loadSubscriptions() { `).join("") : '
Пока нет подписок
'; } +function subStatus(s) { + if (s.held_at) return "held"; + if (!s.active) return "expired"; + return "active"; +} + +function renderFilteredSubs() { + const q = document.getElementById("subs-search").value.trim().toLowerCase(); + const statusFilter = DD.subsStatusFilter ? DD.subsStatusFilter.getValue() : "all"; + const filtered = allSubs.filter((s) => { + if (statusFilter !== "all" && subStatus(s) !== statusFilter) return false; + if (!q) return true; + const haystack = [ + s.username || "", String(s.tg_id), s.node_label || "", s.plan_label || "", + ].join(" ").toLowerCase(); + return haystack.includes(q); + }); + renderSubsTable(filtered); +} + +async function loadSubscriptions() { + allSubs = await api("/admin/api/subscriptions"); + renderFilteredSubs(); +} + let devicesTgId = null; async function openUserCard(tgId, label) { devicesTgId = tgId;