Require asset ID scan in audit and consume modals
Build and push image / build (push) Successful in 47s
Build and push image / build (push) Successful in 47s
No default item selection — modals open with a scan prompt. Form fields appear only after scanning an asset ID. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,7 @@ export function AuditFlow({
|
||||
.filter((i) => i.status === "active")
|
||||
.sort((a, b) => helpers.daysSinceCheck(b) - helpers.daysSinceCheck(a));
|
||||
|
||||
const [itemId, setItemId] = useState(initialItem?.id ?? overdueFirst[0]?.id ?? "");
|
||||
const [itemId, setItemId] = useState(initialItem?.id ?? "");
|
||||
const [date, setDate] = useState(TODAY_STR);
|
||||
const [confirmedBy, setConfirmedBy] = useState<"asset" | "SKU" | "visual">("asset");
|
||||
|
||||
@@ -82,17 +82,17 @@ export function AuditFlow({
|
||||
}
|
||||
};
|
||||
|
||||
if (!item) return null;
|
||||
const auditMode = cfg?.auditMode ?? "weigh";
|
||||
const ml = AUDIT_MODE_LABELS[auditMode] ?? AUDIT_MODE_LABELS.weigh!;
|
||||
|
||||
const last = helpers.lastAudit(item);
|
||||
const prevValue =
|
||||
item.kind === "discrete"
|
||||
const last = item ? helpers.lastAudit(item) : null;
|
||||
const prevValue = item
|
||||
? item.kind === "discrete"
|
||||
? item.countLastAudit ?? item.countOriginal
|
||||
: last
|
||||
? last.value
|
||||
: item.weight;
|
||||
: item.weight
|
||||
: 0;
|
||||
|
||||
const delta = Number(value) - prevValue;
|
||||
|
||||
@@ -108,7 +108,7 @@ export function AuditFlow({
|
||||
boxShadow: "var(--shadow-lg)",
|
||||
}}
|
||||
>
|
||||
<ModalHeader title={ml.title} eyebrow="" onClose={onClose} />
|
||||
<ModalHeader title={item ? ml.title : "Audit"} eyebrow="" onClose={onClose} />
|
||||
|
||||
<div style={{ padding: 32 }}>
|
||||
<ScanField
|
||||
@@ -118,6 +118,12 @@ export function AuditFlow({
|
||||
onMatch={handleScan}
|
||||
/>
|
||||
|
||||
{!item ? (
|
||||
<div style={{ marginTop: 24, textAlign: "center", color: "var(--ink-3)", fontSize: 13, fontStyle: "italic", padding: "24px 0" }}>
|
||||
Scan an asset ID to continue.
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 16,
|
||||
@@ -226,6 +232,8 @@ export function AuditFlow({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div style={{ marginTop: 14, fontSize: 12, color: "var(--terracotta)" }}>{error}</div>
|
||||
@@ -234,14 +242,14 @@ export function AuditFlow({
|
||||
|
||||
<ModalFooter>
|
||||
<div style={{ fontSize: 12, color: "var(--ink-3)" }}>
|
||||
Next audit due in {cfg?.cadenceDays}d
|
||||
{item ? `Next audit due in ${cfg?.cadenceDays}d` : ""}
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 8 }}>
|
||||
<Btn variant="ghost" onClick={onClose}>Cancel</Btn>
|
||||
<Btn
|
||||
variant="primary"
|
||||
icon="check"
|
||||
disabled={audit.isPending}
|
||||
disabled={audit.isPending || !item}
|
||||
onClick={() => audit.mutate()}
|
||||
>
|
||||
{audit.isPending ? "Saving…" : "Save audit"}
|
||||
|
||||
@@ -22,7 +22,7 @@ export function ConsumeFlow({
|
||||
const { toast } = useToast();
|
||||
const allItems = enrichItems(data);
|
||||
const active = allItems.filter((i) => i.status === "active");
|
||||
const [itemId, setItemId] = useState(initialItem?.id ?? active[0]?.id ?? "");
|
||||
const [itemId, setItemId] = useState(initialItem?.id ?? "");
|
||||
const [rating, setRating] = useState(4);
|
||||
const [notes, setNotes] = useState("");
|
||||
const [date, setDate] = useState(TODAY_STR);
|
||||
@@ -46,9 +46,8 @@ export function ConsumeFlow({
|
||||
}
|
||||
};
|
||||
|
||||
if (!item) return null;
|
||||
const bin = data.bins.find((b) => b.id === item.binId);
|
||||
const lifespan = Math.round((+new Date(date) - +new Date(item.purchaseDate)) / 86_400_000);
|
||||
const bin = item ? data.bins.find((b) => b.id === item.binId) : undefined;
|
||||
const lifespan = item ? Math.round((+new Date(date) - +new Date(item.purchaseDate)) / 86_400_000) : 0;
|
||||
|
||||
return (
|
||||
<ModalBackdrop onClose={onClose}>
|
||||
@@ -72,6 +71,12 @@ export function ConsumeFlow({
|
||||
onMatch={handleScan}
|
||||
/>
|
||||
|
||||
{!item ? (
|
||||
<div style={{ marginTop: 24, textAlign: "center", color: "var(--ink-3)", fontSize: 13, fontStyle: "italic", padding: "24px 0" }}>
|
||||
Scan an asset ID to continue.
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 16,
|
||||
@@ -150,6 +155,8 @@ export function ConsumeFlow({
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div style={{ marginTop: 14, fontSize: 12, color: "var(--terracotta)" }}>{error}</div>
|
||||
@@ -163,7 +170,7 @@ export function ConsumeFlow({
|
||||
<Btn
|
||||
variant="primary"
|
||||
icon="check"
|
||||
disabled={finish.isPending}
|
||||
disabled={finish.isPending || !item}
|
||||
onClick={() => finish.mutate()}
|
||||
>
|
||||
{finish.isPending ? "Saving…" : "Mark consumed"}
|
||||
|
||||
Reference in New Issue
Block a user