// ── Items page ──────────────────────────────────────────────────────────────── const ITEMS_PAGE_SIZE = 50; function ItemsPage() { const [chain, setChain] = React.useState("all"); const [data, setData] = React.useState(null); const [error, setError] = React.useState(null); const [refreshKey, setRefreshKey] = React.useState(0); const [expandedItem, setExpandedItem] = React.useState(null); const [page, setPage] = React.useState(0); const [scanning, setScanning] = React.useState(false); const videoRef = React.useRef(null); const readerRef = React.useRef(null); const colors = useChainColors(); // Start/stop camera with ZXing for barcode scan React.useEffect(() => { if (!scanning) return; if (!videoRef.current) return; const reader = new ZXing.BrowserMultiFormatReader(); readerRef.current = reader; reader .decodeFromVideoDevice(undefined, videoRef.current, (result) => { if (!result) return; const text = result.getText(); reader.reset(); readerRef.current = null; setScanning(false); window.location.hash = `#/item/${encodeURIComponent(text)}`; }) .catch(() => setScanning(false)); return () => { reader.reset(); readerRef.current = null; }; }, [scanning]); function stopScan() { readerRef.current?.reset(); readerRef.current = null; setScanning(false); } React.useEffect(() => { setData(null); fetch( `/api/items?chain=${encodeURIComponent(chain)}&page=${page}&page_size=${ITEMS_PAGE_SIZE}`, ) .then((r) => (r.ok ? r.json() : Promise.reject(r.status))) .then((d) => { setData(d); if (chain !== "all" && !d.chains.includes(chain)) setChain("all"); }) .catch((e) => setError(String(e))); }, [chain, page, refreshKey]); async function deleteMatch(itemName, itemChain) { const c = itemChain || chain; if (!confirm(`Rimuovere l'abbinamento per: ${itemName}?`)) return; await fetch( `/api/match/${encodeURIComponent(c)}/${encodeURIComponent(itemName)}`, { method: "DELETE" }, ); setRefreshKey((k) => k + 1); } if (error) return
Errore: {error}
; if (!data) return (Caricamento prodotti…
); const { items, total_count, chains, mongo_ok } = data; const visibleItems = items; const totalPages = Math.ceil(total_count / ITEMS_PAGE_SIZE); return (Nessun prodotto abbinato
Apri uno scontrino e abbina gli articoli ai prodotti per vederli qui.