import { useCallback, useEffect, useRef, useState } from 'react'; import { useFocusTrap } from '../../lib/use-focus-trap'; import { VOCAB } from '../../lib/collection-vocabulary.js'; import { Button } from '../ui'; import GlassSurface from '../ui/GlassSurface.js'; import ReviewCardItem from './ReviewCardItem'; function confidencePercent(confidence) { if (confidence == null || Number.isNaN(confidence)) return null; return confidence <= 1 ? Math.round(confidence * 100) : Math.round(confidence); } function CheckoutFooter({ selectedCount, isProcessing, commitError, onCommitOwned, onOpenListPicker, }) { const selectHintId = 'checkout-select-hint'; return (
{commitError && (
{commitError}
)} {selectedCount === 0 && (

Select at least one card

)}
); } export function ScannerCheckoutContent({ queue, onOpenListPicker, onEmpty, headerId = 'checkout-sheet-title', }) { const [commitError, setCommitError] = useState(null); const initialSelectionDoneRef = useRef(false); const cartCards = queue.scannedCards.filter((card) => !card.processed); const selectedCount = cartCards.filter((card) => queue.selectedCards.has(card.id)).length; const lowConfidenceCount = cartCards.filter((card) => { const pct = confidencePercent(card.confidence); return pct != null && pct < 70; }).length; useEffect(() => { if (initialSelectionDoneRef.current) return; cartCards.forEach((card) => { if (!queue.selectedCards.has(card.id)) { queue.toggleCardSelection(card.id); } }); initialSelectionDoneRef.current = true; }, [cartCards, queue]); useEffect(() => { if (cartCards.length === 0) { onEmpty?.(); } }, [cartCards.length, onEmpty]); const handleCommitOwned = async () => { setCommitError(null); const beforeIds = cartCards .filter((card) => queue.selectedCards.has(card.id)) .map((card) => card.id); if (beforeIds.length === 0) return; const successfulIds = await queue.commitSelectedToOwned(); if (!successfulIds?.length) { setCommitError('Could not add cards. Try again.'); } }; return ( <>

{cartCards.length} {cartCards.length === 1 ? 'card' : 'cards'} scanned

{lowConfidenceCount > 0 && (

{lowConfidenceCount} {lowConfidenceCount === 1 ? 'needs' : 'need'} review

)}
{cartCards.map((card) => ( queue.toggleCardSelection(card.id)} showCheckbox confidence={card.confidence} onIncrement={() => queue.incrementCardQuantity(card.id)} onDecrement={() => queue.decrementCardQuantity(card.id)} onUpdateMetadata={(patch) => queue.updateCardMetadata(card.id, patch)} onRemove={() => queue.removeScannedCard(card.id)} isAdding={queue.addingCardIds?.has(card.id)} /> ))}
); } export default function ScannerCheckoutSheet({ queue, onClose, onOpenListPicker, trapActive = true, }) { const sheetRef = useFocusTrap(trapActive); const backdropRef = useRef(null); useEffect(() => { const backdrop = backdropRef.current; const sheet = sheetRef.current; if (!backdrop || !sheet) return undefined; requestAnimationFrame(() => { backdrop.dataset.visible = 'true'; sheet.dataset.visible = 'true'; }); if (!trapActive) return undefined; const handler = (e) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', handler); return () => document.removeEventListener('keydown', handler); }, [onClose, sheetRef, trapActive]); const handleBackdropClick = useCallback( (e) => { if (e.target === e.currentTarget) onClose(); }, [onClose] ); return (
); }