+ {bins.map((bin) => {
+ const items = data.products.filter(
+ (p) => p.binId === bin.id && p.status === "active",
+ );
+ // Discrete products (pre-rolls, edibles, vapes) take a slot per unit;
+ // bulk products take one slot per jar/container.
+ const slotsUsed = items.reduce(
+ (s, p) =>
+ s + (p.kind === "discrete" ? (p.countLastAudit ?? p.countOriginal) : 1),
+ 0,
+ );
+ const fillPct = slotsUsed / bin.capacity;
+ const totalValue = items.reduce(
+ (s, p) => s + p.price * helpers.pctRemaining(p, TODAY_STR),
+ 0,
+ );
+ return (
+
+
- {TYPE_GLYPHS[p.type]}
+
+ {bin.name}
+
+
+
{slotsUsed} / {bin.capacity}
+
+
+
-
+
+ {fmt.money(totalValue)}
+
+
0.9
+ ? "var(--terracotta)"
+ : fillPct > 0.7
+ ? "var(--amber)"
+ : "var(--sage)",
}}
- >
- {p.name}
-
-
- {helpers.brandName(data, p.brandId)}
-
-
-
- {remainingShort(p)}
+ />
- ))}
-
-
- );
- })}
-
+ {items.length === 0 && (
+
+ Empty
+
+ )}
+ {items.map((p) => (
+
onSelectProduct(p)}
+ style={{
+ display: "flex",
+ alignItems: "center",
+ gap: 10,
+ padding: "8px 14px",
+ borderRadius: "var(--r-sm)",
+ cursor: "pointer",
+ }}
+ >
+
+ {TYPE_GLYPHS[p.type]}
+
+
+
+ {p.name}
+
+
+ {helpers.brandName(data, p.brandId)}
+
+
+
+ {remainingShort(p)}
+
+
+ ))}
+