filter, export

This commit is contained in:
oliver
2026-06-10 15:24:50 -03:00
parent 5c881d0c93
commit b7381949c6
2 changed files with 77 additions and 3 deletions
+58 -2
View File
@@ -46,7 +46,8 @@ let wizardSelectedSkills = new Set();
let wizardSelectedIntegrations = new Set(); let wizardSelectedIntegrations = new Set();
let wizardFieldValues = {}; // { stepIndex: { fieldKey: value } } let wizardFieldValues = {}; // { stepIndex: { fieldKey: value } }
let wizardIntegrationStep = 0; // current index in fields phase let wizardIntegrationStep = 0; // current index in fields phase
let wizardSelectedIntegrationList = []; // ordered list of selected integration objects let wizardSelectedIntegrationList = [];
let invoicesData = []; // cached full invoice list for filtering/export
/* ─── Debug logger ─────────────────────────────────────────── */ /* ─── Debug logger ─────────────────────────────────────────── */
function dbg(label, data) { function dbg(label, data) {
@@ -1196,7 +1197,10 @@ async function loadInvoices() {
} else { } else {
data = []; data = [];
} }
renderInvoices(data); invoicesData = data;
applyInvoiceFilter();
const filterInput = document.getElementById("invoice-filter");
if (filterInput) filterInput.value = "";
} catch (err) { } catch (err) {
dbg("\u2190 Invoices error", err.message); dbg("\u2190 Invoices error", err.message);
body.innerHTML = body.innerHTML =
@@ -1204,6 +1208,22 @@ async function loadInvoices() {
} }
} }
function applyInvoiceFilter() {
const q = (
document.getElementById("invoice-filter").value || ""
).toLowerCase();
const filtered = q
? invoicesData.filter(
(inv) =>
(inv.date || "").toLowerCase().includes(q) ||
(inv.uuid || "").toLowerCase().includes(q) ||
(inv.product || "").toLowerCase().includes(q) ||
(inv.price || "").toLowerCase().includes(q),
)
: invoicesData;
renderInvoices(filtered);
}
function renderInvoices(data) { function renderInvoices(data) {
const body = document.getElementById("invoices-body"); const body = document.getElementById("invoices-body");
if (!data.length) { if (!data.length) {
@@ -1233,6 +1253,42 @@ function renderInvoices(data) {
</div>`; </div>`;
} }
function exportInvoicesCSV() {
const q = (
document.getElementById("invoice-filter").value || ""
).toLowerCase();
const filtered = q
? invoicesData.filter(
(inv) =>
(inv.date || "").toLowerCase().includes(q) ||
(inv.uuid || "").toLowerCase().includes(q) ||
(inv.product || "").toLowerCase().includes(q) ||
(inv.price || "").toLowerCase().includes(q),
)
: invoicesData;
if (!filtered.length) {
toast("No invoices to export.", "warning");
return;
}
const rows = ["Date,Agent,Product,Price"];
for (const inv of filtered) {
rows.push(
[inv.date || "", inv.uuid || "", inv.product || "", inv.price || ""].join(
",",
),
);
}
const blob = new Blob([rows.join("\n")], { type: "text/csv" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "invoices.csv";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
/* ═══════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════
RESTART RESTART
═══════════════════════════════════════════════════════════════ */ ═══════════════════════════════════════════════════════════════ */
+18
View File
@@ -937,7 +937,25 @@
<div class="account-col-divider"></div> <div class="account-col-divider"></div>
<!-- ── Right: invoices ──────────────────────── --> <!-- ── Right: invoices ──────────────────────── -->
<div class="account-col account-col--invoices"> <div class="account-col account-col--invoices">
<div class="acct-invoices-toolbar">
<div class="acct-invoices-title">Invoices</div> <div class="acct-invoices-title">Invoices</div>
<div class="acct-invoices-actions">
<input
type="text"
id="invoice-filter"
class="invoice-filter-input"
placeholder="Filter invoices…"
oninput="applyInvoiceFilter()"
/>
<button
type="button"
class="btn btn-ghost btn-sm"
onclick="exportInvoicesCSV()"
>
Export CSV
</button>
</div>
</div>
<div id="invoices-body"></div> <div id="invoices-body"></div>
</div> </div>
</div> </div>