mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-03-25 09:25:51 +00:00
fix: Pending js
This commit is contained in:
parent
b8062b010f
commit
fb584e7f41
1 changed files with 138 additions and 0 deletions
|
|
@ -0,0 +1,138 @@
|
|||
// viz/app/pending.js
|
||||
const LS_KEY = "stviz:v1:pendingSkuEdits";
|
||||
|
||||
function safeParseJson(s) {
|
||||
try {
|
||||
return JSON.parse(String(s || ""));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function loadPendingEdits() {
|
||||
const raw = (() => {
|
||||
try {
|
||||
return localStorage.getItem(LS_KEY) || "";
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
})();
|
||||
|
||||
const j = safeParseJson(raw);
|
||||
const links = Array.isArray(j?.links) ? j.links : [];
|
||||
const ignores = Array.isArray(j?.ignores) ? j.ignores : [];
|
||||
|
||||
return {
|
||||
links: links
|
||||
.map((x) => ({
|
||||
fromSku: String(x?.fromSku || "").trim(),
|
||||
toSku: String(x?.toSku || "").trim(),
|
||||
}))
|
||||
.filter((x) => x.fromSku && x.toSku && x.fromSku !== x.toSku),
|
||||
ignores: ignores
|
||||
.map((x) => ({
|
||||
skuA: String(x?.skuA || x?.a || "").trim(),
|
||||
skuB: String(x?.skuB || x?.b || "").trim(),
|
||||
}))
|
||||
.filter((x) => x.skuA && x.skuB && x.skuA !== x.skuB),
|
||||
createdAt: String(j?.createdAt || ""),
|
||||
};
|
||||
}
|
||||
|
||||
export function savePendingEdits(edits) {
|
||||
const out = {
|
||||
createdAt: edits?.createdAt || new Date().toISOString(),
|
||||
links: Array.isArray(edits?.links) ? edits.links : [],
|
||||
ignores: Array.isArray(edits?.ignores) ? edits.ignores : [],
|
||||
};
|
||||
try {
|
||||
localStorage.setItem(LS_KEY, JSON.stringify(out));
|
||||
} catch {}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function clearPendingEdits() {
|
||||
try {
|
||||
localStorage.removeItem(LS_KEY);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function canonicalPairKey(a, b) {
|
||||
const x = String(a || "").trim();
|
||||
const y = String(b || "").trim();
|
||||
if (!x || !y) return "";
|
||||
return x < y ? `${x}|${y}` : `${y}|${x}`;
|
||||
}
|
||||
|
||||
export function addPendingLink(fromSku, toSku) {
|
||||
const f = String(fromSku || "").trim();
|
||||
const t = String(toSku || "").trim();
|
||||
if (!f || !t || f === t) return false;
|
||||
|
||||
const edits = loadPendingEdits();
|
||||
const k = `${f}→${t}`;
|
||||
const seen = new Set(edits.links.map((x) => `${x.fromSku}→${x.toSku}`));
|
||||
if (seen.has(k)) return false;
|
||||
|
||||
edits.links.push({ fromSku: f, toSku: t });
|
||||
savePendingEdits(edits);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function addPendingIgnore(skuA, skuB) {
|
||||
const a = String(skuA || "").trim();
|
||||
const b = String(skuB || "").trim();
|
||||
if (!a || !b || a === b) return false;
|
||||
|
||||
const edits = loadPendingEdits();
|
||||
const k = canonicalPairKey(a, b);
|
||||
const seen = new Set(edits.ignores.map((x) => canonicalPairKey(x.skuA, x.skuB)));
|
||||
if (seen.has(k)) return false;
|
||||
|
||||
edits.ignores.push({ skuA: a, skuB: b });
|
||||
savePendingEdits(edits);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function pendingCounts() {
|
||||
const e = loadPendingEdits();
|
||||
return { links: e.links.length, ignores: e.ignores.length, total: e.links.length + e.ignores.length };
|
||||
}
|
||||
|
||||
export function applyPendingToMeta(meta) {
|
||||
const base = {
|
||||
generatedAt: String(meta?.generatedAt || ""),
|
||||
links: Array.isArray(meta?.links) ? meta.links.slice() : [],
|
||||
ignores: Array.isArray(meta?.ignores) ? meta.ignores.slice() : [],
|
||||
};
|
||||
|
||||
const p = loadPendingEdits();
|
||||
|
||||
// merge links (dedupe by from→to)
|
||||
const seenL = new Set(
|
||||
base.links.map((x) => `${String(x?.fromSku || "").trim()}→${String(x?.toSku || "").trim()}`)
|
||||
);
|
||||
for (const x of p.links) {
|
||||
const k = `${x.fromSku}→${x.toSku}`;
|
||||
if (!seenL.has(k)) {
|
||||
seenL.add(k);
|
||||
base.links.push({ fromSku: x.fromSku, toSku: x.toSku });
|
||||
}
|
||||
}
|
||||
|
||||
// merge ignores (dedupe by canonical pair key)
|
||||
const seenI = new Set(
|
||||
base.ignores.map((x) =>
|
||||
canonicalPairKey(String(x?.skuA || x?.a || "").trim(), String(x?.skuB || x?.b || "").trim())
|
||||
)
|
||||
);
|
||||
for (const x of p.ignores) {
|
||||
const k = canonicalPairKey(x.skuA, x.skuB);
|
||||
if (!seenI.has(k)) {
|
||||
seenI.add(k);
|
||||
base.ignores.push({ skuA: x.skuA, skuB: x.skuB });
|
||||
}
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
Loading…
Reference in a new issue