From 4695e31713f6d19e4805639c7129951ed58496a0 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Thu, 13 Nov 2025 16:38:12 +0530 Subject: [PATCH] Table Component Updated the Sort Logic --- src/components/Table.astro | 153 ++++++++++++++++++++++++++++++------- 1 file changed, 127 insertions(+), 26 deletions(-) diff --git a/src/components/Table.astro b/src/components/Table.astro index 502a8db..b423151 100644 --- a/src/components/Table.astro +++ b/src/components/Table.astro @@ -37,6 +37,8 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; ) } +
+
{ + e.stopPropagation(); + removeBadge(key); + }); + } + } + + function badgeTemplate(key, order) { + // returns HTML string for a badge; includes data-key and close button + return ` + + ${escapeHtml(key)}: ${escapeHtml(order)} + + + `; + } + + function removeBadge(key) { + // remove from DOM + const el = badgeContainer.querySelector( + `[data-badge-key="${key}"]`, + ); + if (el) el.remove(); + + // remove from sort map + if (sort.hasOwnProperty(key)) { + delete sort[key]; + } + + // update header indicator (if any) + const th = Array.from(sortHeaders).find( + (t) => t.dataset.sortKey === key, + ); + if (th) { + const indicator = th.querySelector(".sort-indicator"); + if (indicator) { + indicator.setAttribute( + "data-icon", + "solar:sort-vertical-line-duotone", + ); + } + } + + // reload data + currentPage = 1; + loadData(); + } + + function escapeHtml(str) { + return String(str) + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } + + // ---------- ROW rendering (unchanged) ---------- function renderRows(dataset) { tbody.innerHTML = ""; mobileBody.innerHTML = ""; @@ -343,26 +428,23 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; } // sort locally if needed - if (Object.keys(sort).length !== 0) { - for (const key in sort) { - const colKey = key; - const colSortOrder = sort[key]; - if (colKey) { - currentData.sort((a, b) => { - const aVal = String(a[colKey] ?? ""); - const bVal = String(b[colKey] ?? ""); - if (aVal < bVal) - return colSortOrder === "asc" ? -1 : 1; - if (aVal > bVal) - return colSortOrder === "asc" ? 1 : -1; - return 0; - }); - } - } + const sortKeys = Object.keys(sort); + if (sortKeys.length !== 0) { + // stable multi-sort — apply keys in reverse so the first sort key has priority + sortKeys.reverse().forEach((k) => { + const colKey = k; + const colSortOrder = sort[k]; + currentData.sort((a, b) => { + const aVal = String(a[colKey] ?? ""); + const bVal = String(b[colKey] ?? ""); + if (aVal < bVal) return colSortOrder === "asc" ? -1 : 1; + if (aVal > bVal) return colSortOrder === "asc" ? 1 : -1; + return 0; + }); + }); } // paginate - renderRows(paginated); renderPagination(totalRows); } @@ -432,10 +514,12 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; }); // 🧭 Sorting - sortHeaders.forEach((th, index) => { + sortHeaders.forEach((th) => { th.addEventListener("click", () => { const key = th.dataset.sortKey; + if (!key) return; + // compute new sort order let sortOrder = "asc"; if (sort.hasOwnProperty(key)) { sortOrder = sort[key] === "asc" ? "desc" : "asc"; @@ -444,13 +528,30 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; sort[key] = sortOrder; } - th.querySelector(".sort-indicator")?.setAttribute( - "data-icon", - sortOrder === "asc" - ? "solar:sort-up-bold-duotone" - : "solar:sort-down-bold-duotone", - ); + // update header icon (single header) + sortHeaders.forEach((h) => { + const ind = h.querySelector(".sort-indicator"); + if (!ind) return; + if (h.dataset.sortKey === key) { + ind.setAttribute( + "data-icon", + sortOrder === "asc" + ? "solar:sort-up-bold-duotone" + : "solar:sort-down-bold-duotone", + ); + } else { + ind.setAttribute( + "data-icon", + "solar:sort-vertical-line-duotone", + ); + } + }); + // create / update badge + createOrUpdateBadge(key, sort[key]); + + // reload data + currentPage = 1; loadData(); }); });