mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-03-25 09:25:51 +00:00
feat: UX Changes
This commit is contained in:
parent
6d737d7c22
commit
f912ce1ccc
1 changed files with 22 additions and 16 deletions
|
|
@ -914,11 +914,8 @@ export async function renderItem($app, skuInput) {
|
||||||
// --- Compute marker values ---
|
// --- Compute marker values ---
|
||||||
// Province medians: per-store mean over time, then median across stores (>=3 stores)
|
// Province medians: per-store mean over time, then median across stores (>=3 stores)
|
||||||
const storeMeans = seriesSorted
|
const storeMeans = seriesSorted
|
||||||
.map((s) => ({
|
.map((s) => ({ label: s.label, mean: weightedMeanByDuration(s.points, labels) }))
|
||||||
label: s.label,
|
.filter((x) => Number.isFinite(x.mean));
|
||||||
mean: weightedMeanByDuration(s.points, labels), // duration-weighted
|
|
||||||
}))
|
|
||||||
.filter((x) => Number.isFinite(x.mean));
|
|
||||||
|
|
||||||
const bcMeans = storeMeans.filter((x) => isBcStoreLabel(x.label));
|
const bcMeans = storeMeans.filter((x) => isBcStoreLabel(x.label));
|
||||||
const abMeans = storeMeans.filter((x) => !isBcStoreLabel(x.label));
|
const abMeans = storeMeans.filter((x) => !isBcStoreLabel(x.label));
|
||||||
|
|
@ -926,25 +923,34 @@ export async function renderItem($app, skuInput) {
|
||||||
const markers = [];
|
const markers = [];
|
||||||
|
|
||||||
if (bcMeans.length >= 3) {
|
if (bcMeans.length >= 3) {
|
||||||
const y = medianFinite(bcMeans.map((x) => x.mean));
|
const y = medianFinite(bcMeans.map((x) => x.mean));
|
||||||
if (Number.isFinite(y)) markers.push({ y: Math.round(y), text: "BC" });
|
if (Number.isFinite(y)) markers.push({ y: Math.round(y), text: "BC" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abMeans.length >= 3) {
|
if (abMeans.length >= 3) {
|
||||||
const y = medianFinite(abMeans.map((x) => x.mean));
|
const y = medianFinite(abMeans.map((x) => x.mean));
|
||||||
if (Number.isFinite(y)) markers.push({ y: Math.round(y), text: "Alberta" });
|
if (Number.isFinite(y)) markers.push({ y: Math.round(y), text: "Alberta" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Target price: pick 3 lowest per-store mins (distinct stores), then average (>=3 stores)
|
// Target price: pick 3 lowest per-store mins (distinct stores), then average (>=3 stores)
|
||||||
const storeMins = seriesSorted
|
// Only show if there are at least 6 total unique price points (finite) across the chart.
|
||||||
.map((s) => ({ label: s.label, min: minFinite(s.values) }))
|
const uniquePricePoints = new Set(
|
||||||
.filter((x) => Number.isFinite(x.min))
|
allVals
|
||||||
.sort((a, b) => a.min - b.min);
|
.filter((v) => Number.isFinite(v))
|
||||||
|
.map((v) => Math.round(v * 100)) // cents to avoid float noise
|
||||||
|
);
|
||||||
|
const hasEnoughUniquePoints = uniquePricePoints.size >= 6;
|
||||||
|
|
||||||
if (storeMins.length >= 3) {
|
const storeMins = seriesSorted
|
||||||
const t = (storeMins[0].min + storeMins[1].min + storeMins[2].min) / 3;
|
.map((s) => ({ label: s.label, min: minFinite(s.values) }))
|
||||||
if (Number.isFinite(t)) markers.push({ y: Math.round(t), text: "Target" });
|
.filter((x) => Number.isFinite(x.min))
|
||||||
|
.sort((a, b) => a.min - b.min);
|
||||||
|
|
||||||
|
if (hasEnoughUniquePoints && storeMins.length >= 3) {
|
||||||
|
const t = (storeMins[0].min + storeMins[1].min + storeMins[2].min) / 3;
|
||||||
|
if (Number.isFinite(t)) markers.push({ y: Math.round(t), text: "Target" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const markerYs = markers.map((m) => Number(m.y)).filter(Number.isFinite);
|
const markerYs = markers.map((m) => Number(m.y)).filter(Number.isFinite);
|
||||||
|
|
||||||
// helper: approximate font px size from a CSS font string (Chart uses one)
|
// helper: approximate font px size from a CSS font string (Chart uses one)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue