import { useEffect, useState } from "react"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import type { Bootstrap, Item } from "../../types.js"; import { helpers, enrichItems } from "../../types.js"; import { getToday, getStoredTimezone } from "../../tz.js"; import { fmt } from "../../format.js"; import { api } from "../../api.js"; import { Btn, Field, Icon, Input, Textarea } from "../primitives/index.js"; import { ScanField, type ScanResult } from "../ScanField.js"; import { ModalBackdrop, ModalHeader, ModalFooter } from "./ModalChrome.js"; import { useToast } from "../Toast.js"; export function ConsumeFlow({ data, onClose, item: initialItem, }: { data: Bootstrap; onClose: () => void; item: Item | null; }) { const qc = useQueryClient(); const { toast } = useToast(); const allItems = enrichItems(data); const active = allItems.filter((i) => i.status === "active" || i.status === "checked-out"); const [itemId, setItemId] = useState(initialItem?.id ?? ""); const [rating, setRating] = useState(null); const [notes, setNotes] = useState(""); const [date, setDate] = useState(getToday(getStoredTimezone())); const [error, setError] = useState(null); const [confirming, setConfirming] = useState(false); const item = allItems.find((i) => i.id === itemId); useEffect(() => { setError(null); setConfirming(false); }, [itemId]); const finish = useMutation({ mutationFn: () => api.finishInventoryItem(itemId, { date, rating: rating ?? undefined, notes }), onSuccess: () => { qc.invalidateQueries({ queryKey: ["bootstrap"] }); const ratingStr = rating != null ? ` — ${rating}/5 stars` : ""; const undoItemId = itemId; const undoBinId = item?.binId ?? data.bins[0]?.id ?? ""; toast(`Marked ${item?.name ?? "item"} as consumed${ratingStr}`, "success", { label: "Undo", onClick: () => { api.reactivateInventoryItem(undoItemId, { binId: undoBinId }).then(() => { qc.invalidateQueries({ queryKey: ["bootstrap"] }); }); }, }); onClose(); }, onError: (e: Error) => setError(e.message), }); const handleScan = (result: ScanResult) => { if (result.kind === "item") { setItemId(result.item.id); } }; 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 (
{!item ? (
Scan an asset ID to continue.
) : ( <>
{item.name}
{item.assetId} · {helpers.brandName(data, item.brandId)} · {bin?.name} · purchased{" "} {fmt.dateShort(item.purchaseDate, getStoredTimezone())}
LASTED
{lifespan} days
setDate(e.target.value)} />
{[1, 2, 3, 4, 5].map((n) => ( ))} {rating != null ? `${rating}/5` : "—"}