Scope ScanField by mode: asset ID only for audit/consume, SKU only for add inventory
Build and push image / build (push) Successful in 57s
Build and push image / build (push) Successful in 57s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ export function ScanField({
|
||||
onMatch,
|
||||
onScanNoMatch,
|
||||
matchedLabel,
|
||||
mode = "both",
|
||||
}: {
|
||||
items: Item[];
|
||||
products?: Product[];
|
||||
@@ -25,6 +26,7 @@ export function ScanField({
|
||||
// open a "create new product" form prefilled with the scanned SKU).
|
||||
onScanNoMatch?: (raw: string) => void;
|
||||
matchedLabel: string | null;
|
||||
mode?: "both" | "assetId" | "sku";
|
||||
}) {
|
||||
const [scan, setScan] = useState("");
|
||||
const [feedback, setFeedback] = useState<{ type: "matched" | "miss"; text: string } | null>(null);
|
||||
@@ -35,7 +37,7 @@ export function ScanField({
|
||||
setFeedback(null);
|
||||
return;
|
||||
}
|
||||
const hit = lookup(trimmed, items, products);
|
||||
const hit = lookup(trimmed, items, products, mode);
|
||||
if (hit) {
|
||||
const label = hit.kind === "item" ? hit.item.name : hit.product.sku;
|
||||
onMatch(hit);
|
||||
@@ -50,13 +52,16 @@ export function ScanField({
|
||||
if (!scan.trim() || feedback?.type === "matched") return;
|
||||
const timer = setTimeout(() => {
|
||||
const raw = scan.trim();
|
||||
if (!lookup(raw.toLowerCase(), items, products)) {
|
||||
if (!lookup(raw.toLowerCase(), items, products, mode)) {
|
||||
if (onScanNoMatch) {
|
||||
onScanNoMatch(raw);
|
||||
setScan("");
|
||||
setFeedback(null);
|
||||
} else {
|
||||
setFeedback({ type: "miss", text: "No asset id or SKU matches that." });
|
||||
const missText = mode === "assetId" ? "No item matches that asset ID."
|
||||
: mode === "sku" ? "No product matches that SKU."
|
||||
: "No asset id or SKU matches that.";
|
||||
setFeedback({ type: "miss", text: missText });
|
||||
}
|
||||
}
|
||||
}, 400);
|
||||
@@ -64,7 +69,7 @@ export function ScanField({
|
||||
}, [scan, items, products]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<Field label="Scan asset id or SKU">
|
||||
<Field label={mode === "assetId" ? "Scan asset ID" : mode === "sku" ? "Scan SKU" : "Scan asset id or SKU"}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
@@ -80,7 +85,7 @@ export function ScanField({
|
||||
value={scan}
|
||||
onChange={(e) => setScan(e.target.value)}
|
||||
onFocus={(e) => e.currentTarget.select()}
|
||||
placeholder="K3F9X2 or SKU-XXXXXX"
|
||||
placeholder={mode === "assetId" ? "123456" : mode === "sku" ? "SKU-XXXXXX" : "123456 or SKU-XXXXXX"}
|
||||
style={{
|
||||
border: "none",
|
||||
outline: "none",
|
||||
@@ -124,14 +129,19 @@ function lookup(
|
||||
trimmed: string,
|
||||
items: Item[],
|
||||
products?: Product[],
|
||||
mode: "both" | "assetId" | "sku" = "both",
|
||||
): ScanResult | null {
|
||||
const itemHit = items.find((i) => i.assetId.toLowerCase() === trimmed);
|
||||
if (itemHit) return { kind: "item", item: itemHit };
|
||||
const skuHitItem = items.find((i) => i.sku.toLowerCase() === trimmed);
|
||||
if (skuHitItem) return { kind: "item", item: skuHitItem };
|
||||
if (products) {
|
||||
const productHit = products.find((p) => p.sku.toLowerCase() === trimmed);
|
||||
if (productHit) return { kind: "product", product: productHit };
|
||||
if (mode !== "sku") {
|
||||
const itemHit = items.find((i) => i.assetId.toLowerCase() === trimmed);
|
||||
if (itemHit) return { kind: "item", item: itemHit };
|
||||
}
|
||||
if (mode !== "assetId") {
|
||||
const skuHitItem = items.find((i) => i.sku.toLowerCase() === trimmed);
|
||||
if (skuHitItem) return { kind: "item", item: skuHitItem };
|
||||
if (products) {
|
||||
const productHit = products.find((p) => p.sku.toLowerCase() === trimmed);
|
||||
if (productHit) return { kind: "product", product: productHit };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user