mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-04-27 15:07:43 +00:00
UX Improvements
This commit is contained in:
parent
c3702b0ba2
commit
f8896eb031
3 changed files with 80 additions and 14 deletions
|
|
@ -3,6 +3,7 @@ import { parsePriceToNumber, keySkuForRow, displaySku } from "./sku.js";
|
||||||
import { loadIndex } from "./state.js";
|
import { loadIndex } from "./state.js";
|
||||||
import { inferGithubOwnerRepo, githubListCommits, githubFetchFileAtSha, fetchJson } from "./api.js";
|
import { inferGithubOwnerRepo, githubListCommits, githubFetchFileAtSha, fetchJson } from "./api.js";
|
||||||
import { loadSkuRules } from "./mapping.js";
|
import { loadSkuRules } from "./mapping.js";
|
||||||
|
import { storeColor, isWhite } from "./storeColors.js";
|
||||||
|
|
||||||
/* ---------------- Chart lifecycle ---------------- */
|
/* ---------------- Chart lifecycle ---------------- */
|
||||||
|
|
||||||
|
|
@ -665,12 +666,23 @@ export async function renderItem($app, skuInput) {
|
||||||
const span = (ySug.suggestedMax ?? 0) - (ySug.suggestedMin ?? 0);
|
const span = (ySug.suggestedMax ?? 0) - (ySug.suggestedMin ?? 0);
|
||||||
const step = niceStepAtLeast(MIN_STEP, span, MAX_TICKS);
|
const step = niceStepAtLeast(MIN_STEP, span, MAX_TICKS);
|
||||||
|
|
||||||
const datasets = series.map((s) => ({
|
const datasets = series.map((s) => {
|
||||||
label: s.label,
|
const c = storeColor(s.label); // store label
|
||||||
data: labels.map((d) => (s.points.has(d) ? s.points.get(d) : null)),
|
|
||||||
spanGaps: false,
|
return {
|
||||||
tension: 0.15,
|
label: s.label,
|
||||||
}));
|
data: labels.map((d) => (s.points.has(d) ? s.points.get(d) : null)),
|
||||||
|
spanGaps: false,
|
||||||
|
tension: 0.15,
|
||||||
|
|
||||||
|
borderColor: c,
|
||||||
|
backgroundColor: c,
|
||||||
|
pointBackgroundColor: c,
|
||||||
|
pointBorderColor: c,
|
||||||
|
borderWidth: isWhite(c) ? 2 : 1.5,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const ctx = $canvas.getContext("2d");
|
const ctx = $canvas.getContext("2d");
|
||||||
CHART = new Chart(ctx, {
|
CHART = new Chart(ctx, {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
githubFetchFileAtSha,
|
githubFetchFileAtSha,
|
||||||
githubListCommits,
|
githubListCommits,
|
||||||
} from "./api.js";
|
} from "./api.js";
|
||||||
|
import { storeColor, isWhite } from "./storeColors.js";
|
||||||
|
|
||||||
let _chart = null;
|
let _chart = null;
|
||||||
|
|
||||||
|
|
@ -692,14 +693,23 @@ export async function renderStats($app) {
|
||||||
const canvas = document.getElementById("statsChart");
|
const canvas = document.getElementById("statsChart");
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
const datasets = stores.map((s) => ({
|
const datasets = stores.map((s) => {
|
||||||
label: displayStoreName(s),
|
const c = storeColor(s); // store key
|
||||||
data: Array.isArray(seriesByStore[s])
|
|
||||||
? seriesByStore[s]
|
return {
|
||||||
: labels.map(() => null),
|
label: displayStoreName(s),
|
||||||
spanGaps: false,
|
data: Array.isArray(seriesByStore[s]) ? seriesByStore[s] : labels.map(() => null),
|
||||||
tension: 0.15,
|
spanGaps: false,
|
||||||
}));
|
tension: 0.15,
|
||||||
|
|
||||||
|
borderColor: c,
|
||||||
|
backgroundColor: c,
|
||||||
|
pointBackgroundColor: c,
|
||||||
|
pointBorderColor: c,
|
||||||
|
borderWidth: isWhite(c) ? 2 : 1.5,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
if (_chart) {
|
if (_chart) {
|
||||||
_chart.data.labels = labels;
|
_chart.data.labels = labels;
|
||||||
|
|
|
||||||
44
viz/app/storeColors.js
Normal file
44
viz/app/storeColors.js
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
function normalizeStoreId(s) {
|
||||||
|
return String(s || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9]+/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
const STORE_COLOR_OVERRIDES = {
|
||||||
|
strath: "#76B7FF",
|
||||||
|
bsw: "#E9DF7A",
|
||||||
|
kensingtonwinemarket: "#F2C200",
|
||||||
|
vessel: "#FFFFFF",
|
||||||
|
gullliquor: "#6B0F1A",
|
||||||
|
kegncork: "#111111",
|
||||||
|
legacyliquor: "#7B4A12",
|
||||||
|
vintagespirits: "#E34A2C",
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
gull: "#6B0F1A",
|
||||||
|
legacy: "#7B4A12",
|
||||||
|
vintage: "#E34A2C",
|
||||||
|
};
|
||||||
|
|
||||||
|
function hashToHue(str) {
|
||||||
|
let h = 2166136261;
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
h ^= str.charCodeAt(i);
|
||||||
|
h = Math.imul(h, 16777619);
|
||||||
|
}
|
||||||
|
return (h >>> 0) % 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function storeColor(storeKeyOrLabel) {
|
||||||
|
const id = normalizeStoreId(storeKeyOrLabel);
|
||||||
|
const forced = STORE_COLOR_OVERRIDES[id];
|
||||||
|
if (forced) return forced;
|
||||||
|
|
||||||
|
const hue = hashToHue(id || "unknown");
|
||||||
|
return `hsl(${hue} 65% 55%)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isWhite(color) {
|
||||||
|
return String(color).toUpperCase() === "#FFFFFF";
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in a new issue