feat(order-color): add FNV-1a hash helper for per-order color stripes
This commit is contained in:
parent
4985b8c946
commit
6477ebafcc
1 changed files with 44 additions and 0 deletions
44
src/lib/order-color.ts
Normal file
44
src/lib/order-color.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Per-order color helper.
|
||||
*
|
||||
* Hashes an order id into one of six curated Tailwind colours so each
|
||||
* order group renders with a stable, distinct accent on list pages
|
||||
* (Collection Confirm, Invoicing). The same id always picks the same
|
||||
* colour across every render and every page.
|
||||
*
|
||||
* FNV-1a gives an even distribution with no deps. Empty / null ids
|
||||
* fall back to the first palette entry so the helper is total.
|
||||
*/
|
||||
|
||||
export type OrderColor = {
|
||||
/** Left-edge stripe class, e.g. `border-emerald-500/40`. */
|
||||
borderClass: string;
|
||||
/** Faint body tint, e.g. `bg-emerald-500/8`. Available for callers
|
||||
* that want a coloured background; not used by the current pages. */
|
||||
bgClass: string;
|
||||
};
|
||||
|
||||
export const ORDER_COLOR_PALETTE: ReadonlyArray<OrderColor> = [
|
||||
{ borderClass: "border-emerald-500/40", bgClass: "bg-emerald-500/8" },
|
||||
{ borderClass: "border-sky-500/40", bgClass: "bg-sky-500/8" },
|
||||
{ borderClass: "border-amber-500/40", bgClass: "bg-amber-500/8" },
|
||||
{ borderClass: "border-rose-500/40", bgClass: "bg-rose-500/8" },
|
||||
{ borderClass: "border-violet-500/40", bgClass: "bg-violet-500/8" },
|
||||
{ borderClass: "border-teal-500/40", bgClass: "bg-teal-500/8" },
|
||||
];
|
||||
|
||||
const FNV_OFFSET = 0x811c9dc5;
|
||||
const FNV_PRIME = 0x01000193;
|
||||
const PALETTE_SIZE = ORDER_COLOR_PALETTE.length;
|
||||
|
||||
export function colorForOrder(orderId: string | undefined | null): OrderColor {
|
||||
if (!orderId) return ORDER_COLOR_PALETTE[0];
|
||||
let hash = FNV_OFFSET;
|
||||
for (let i = 0; i < orderId.length; i++) {
|
||||
hash ^= orderId.charCodeAt(i);
|
||||
// `>>> 0` keeps the value in the uint32 range so Math.imul
|
||||
// doesn't produce a negative result on overflow.
|
||||
hash = Math.imul(hash, FNV_PRIME) >>> 0;
|
||||
}
|
||||
return ORDER_COLOR_PALETTE[hash % PALETTE_SIZE];
|
||||
}
|
||||
Loading…
Reference in a new issue