diff --git a/viz/app/store_page.js b/viz/app/store_page.js index 276c0de..4be11e5 100644 --- a/viz/app/store_page.js +++ b/viz/app/store_page.js @@ -206,33 +206,19 @@ export async function renderStore($app, storeLabelRaw) { function dateMsFromRow(r) { if (!r) return null; - const keys = [ - "firstSeenAt", - "firstSeen", - "createdAt", - "created", - "addedAt", - "added", - "date", - "ts", - "timestamp", - ]; - for (const k of keys) { - const v = r[k]; - if (v === undefined || v === null) continue; - if (typeof v === "number" && Number.isFinite(v)) { - // If seconds-ish, normalize to ms - if (v > 0 && v < 2e10) return v < 2e9 ? v * 1000 : v; - return v; - } - if (typeof v === "string") { - const t = Date.parse(v); - if (Number.isFinite(t)) return t; - } - } - return null; + + // Match renderItem() semantics: + // 1) prefer precise ts + const t = String(r?.ts || ""); + const ms = t ? Date.parse(t) : NaN; + if (Number.isFinite(ms)) return ms; + + // 2) fall back to date-only (treat as end of day UTC so ordering within day is stable) + const d = String(r?.date || ""); + const ms2 = d ? Date.parse(d + "T23:59:59Z") : NaN; + return Number.isFinite(ms2) ? ms2 : null; } - + // Build earliest "first in DB" timestamp per canonical SKU (includes removed rows) const firstSeenBySku = new Map(); // sku -> ms for (const r of listingsAll) { @@ -715,13 +701,27 @@ export async function renderStore($app, storeLabelRaw) { }); $clearSearch.addEventListener("click", () => { - if (!$q.value) return; - $q.value = ""; - localStorage.setItem(LS_KEY, ""); - applyFilter(); + let changed = false; + + if ($q.value) { + $q.value = ""; + localStorage.setItem(LS_KEY, ""); + changed = true; + } + + // reset max price too (only if slider is active) + if (pageMax !== null) { + selectedMaxPrice = clampAndRound(boundMax); + localStorage.setItem(LS_MAX_PRICE, String(selectedMaxPrice)); + setSliderFromPrice(selectedMaxPrice); + updateMaxPriceLabel(); + changed = true; + } + + if (changed) applyFilter(); $q.focus(); }); - + $exSort.addEventListener("change", () => { localStorage.setItem(LS_EX_SORT, String($exSort.value || "")); applyFilter(); diff --git a/viz/style.css b/viz/style.css index f2fe3f3..82748dc 100644 --- a/viz/style.css +++ b/viz/style.css @@ -255,12 +255,23 @@ a.skuLink:hover { text-decoration: underline; cursor: pointer; } background: #0f1318; color: var(--muted); border-radius: 999px; - padding: 6px 10px; + + /* custom arrow (puts it a bit left from the edge) */ + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239aa6b2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 10px center; + background-size: 12px 12px; + + padding: 6px 28px 6px 10px; /* right padding reserves room for arrow */ font-size: 12px; line-height: 1; outline: none; } + .selectSmall:hover { border-color: #2f3a46; color: var(--text);