mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-03-25 09:25:51 +00:00
viz improvements
This commit is contained in:
parent
d78936a3bc
commit
4276cb6228
1 changed files with 36 additions and 22 deletions
|
|
@ -247,11 +247,7 @@ function makeLimiter(max) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------- History helpers ---------------- */
|
function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel, wantUrls) {
|
||||||
|
|
||||||
// Returns BOTH mins, so we can show a dot on removal day using removed price.
|
|
||||||
// Optimized: pass prebuilt wantRealSkus Set + skuKeys. Keeps behavior identical.
|
|
||||||
function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel) {
|
|
||||||
const items = Array.isArray(obj?.items) ? obj.items : [];
|
const items = Array.isArray(obj?.items) ? obj.items : [];
|
||||||
let liveMin = null;
|
let liveMin = null;
|
||||||
let removedMin = null;
|
let removedMin = null;
|
||||||
|
|
@ -263,29 +259,34 @@ function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel) {
|
||||||
else removedMin = removedMin === null ? p : Math.min(removedMin, p);
|
else removedMin = removedMin === null ? p : Math.min(removedMin, p);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const urlSet = wantUrls instanceof Set ? wantUrls : new Set();
|
||||||
|
const skuKeySet = new Set((Array.isArray(skuKeys) ? skuKeys : []).map((s) => String(s || "")));
|
||||||
|
|
||||||
for (const it of items) {
|
for (const it of items) {
|
||||||
if (!it) continue;
|
if (!it) continue;
|
||||||
|
|
||||||
const isRemoved = Boolean(it.removed);
|
const isRemoved = Boolean(it.removed);
|
||||||
|
const url = String(it.url || "");
|
||||||
|
|
||||||
const real = String(it.sku || "").trim();
|
// 0) URL match (critical for u: keys when storeLabel changes over time)
|
||||||
if (real && wantRealSkus.has(real)) {
|
if (url && urlSet.size && urlSet.has(url)) {
|
||||||
consider(isRemoved, it.price);
|
consider(isRemoved, it.price);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// synthetic match (only relevant if a caller passes u: keys)
|
// 1) Real SKU match (fast path)
|
||||||
if (!real) {
|
const real = String(it.sku || "").trim();
|
||||||
const url = String(it.url || "");
|
if (real && wantRealSkus && wantRealSkus.has(real)) {
|
||||||
for (const skuKey of skuKeys) {
|
|
||||||
const k = String(skuKey || "");
|
|
||||||
if (!k.startsWith("u:")) continue;
|
|
||||||
const row = { sku: "", url, storeLabel: storeLabel || "", store: "" };
|
|
||||||
const kk = keySkuForRow(row);
|
|
||||||
if (kk === k) {
|
|
||||||
consider(isRemoved, it.price);
|
consider(isRemoved, it.price);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2) Fallback: keySkuForRow match (still useful for real SKUs and stable labels)
|
||||||
|
if (skuKeySet.size) {
|
||||||
|
const row = { sku: real, url, storeLabel: storeLabel || "", store: "" };
|
||||||
|
const kk = keySkuForRow(row);
|
||||||
|
if (skuKeySet.has(String(kk || ""))) {
|
||||||
|
consider(isRemoved, it.price);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -293,6 +294,7 @@ function findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeys, storeLabel) {
|
||||||
return { liveMin, removedMin };
|
return { liveMin, removedMin };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function lastFiniteFromEnd(arr) {
|
function lastFiniteFromEnd(arr) {
|
||||||
if (!Array.isArray(arr)) return null;
|
if (!Array.isArray(arr)) return null;
|
||||||
for (let i = arr.length - 1; i >= 0; i--) {
|
for (let i = arr.length - 1; i >= 0; i--) {
|
||||||
|
|
@ -638,6 +640,17 @@ export async function renderItem($app, skuInput) {
|
||||||
),
|
),
|
||||||
).sort();
|
).sort();
|
||||||
|
|
||||||
|
const wantUrlsByVar = new Map(); // vk -> Set(urls)
|
||||||
|
for (const vk of variantKeys) wantUrlsByVar.set(vk, new Set());
|
||||||
|
|
||||||
|
for (const r of rowsAll) {
|
||||||
|
const vk = String(keySkuForRow(r) || "").trim();
|
||||||
|
if (!vk || !wantUrlsByVar.has(vk)) continue;
|
||||||
|
const u = String(r?.url || "").trim();
|
||||||
|
if (u) wantUrlsByVar.get(vk).add(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Split rows by variant for "today" point
|
// Split rows by variant for "today" point
|
||||||
const rowsLiveByVar = new Map();
|
const rowsLiveByVar = new Map();
|
||||||
for (const r of rowsAll) {
|
for (const r of rowsAll) {
|
||||||
|
|
@ -801,7 +814,8 @@ export async function renderItem($app, skuInput) {
|
||||||
const wantRealSkus = new Set([vk].filter((x) => x && !String(x).startsWith("u:")));
|
const wantRealSkus = new Set([vk].filter((x) => x && !String(x).startsWith("u:")));
|
||||||
const skuKeysOne = [vk];
|
const skuKeysOne = [vk];
|
||||||
|
|
||||||
const lastMin = findMinPricesForSkuGroupInDb(objLast, wantRealSkus, skuKeysOne, storeLabel);
|
const wantUrls = wantUrlsByVar.get(vk) || new Set();
|
||||||
|
const lastMin = findMinPricesForSkuGroupInDb(objLast, wantRealSkus, skuKeysOne, storeLabel, wantUrls);
|
||||||
const lastLive = lastMin.liveMin;
|
const lastLive = lastMin.liveMin;
|
||||||
const lastRemoved = lastMin.removedMin;
|
const lastRemoved = lastMin.removedMin;
|
||||||
|
|
||||||
|
|
@ -815,7 +829,7 @@ export async function renderItem($app, skuInput) {
|
||||||
if (firstSha) {
|
if (firstSha) {
|
||||||
try {
|
try {
|
||||||
const objFirst = await loadAtSha(firstSha);
|
const objFirst = await loadAtSha(firstSha);
|
||||||
const firstMin = findMinPricesForSkuGroupInDb(objFirst, wantRealSkus, skuKeysOne, storeLabel);
|
const firstMin = findMinPricesForSkuGroupInDb(objFirst, wantRealSkus, skuKeysOne, storeLabel, wantUrls);
|
||||||
if (firstMin.liveMin !== null) {
|
if (firstMin.liveMin !== null) {
|
||||||
const candidates = [];
|
const candidates = [];
|
||||||
for (let i = 0; i < dayCommits.length - 1; i++) {
|
for (let i = 0; i < dayCommits.length - 1; i++) {
|
||||||
|
|
@ -829,7 +843,7 @@ export async function renderItem($app, skuInput) {
|
||||||
if (!sha) continue;
|
if (!sha) continue;
|
||||||
try {
|
try {
|
||||||
const obj = await loadAtSha(sha);
|
const obj = await loadAtSha(sha);
|
||||||
const m = findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeysOne, storeLabel);
|
const m = findMinPricesForSkuGroupInDb(obj, wantRealSkus, skuKeysOne, storeLabel, wantUrls);
|
||||||
if (m.liveMin !== null) {
|
if (m.liveMin !== null) {
|
||||||
sameDayLastLive = m.liveMin;
|
sameDayLastLive = m.liveMin;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue