import { useEffect, useRef, useState } from 'react'; import { useRouter } from 'next/router'; import Layout from '../components/Layout'; import ScannerCamera from '../components/scanner/ScannerCamera'; import ScannerReview from '../components/scanner/ScannerReview'; import ScannerCheckoutSheet from '../components/scanner/ScannerCheckoutSheet'; import { Modal, Button } from '../components/ui'; import { useAuth } from '../lib/use-auth'; import { useScannerSession } from '../lib/use-scanner-session.js'; import { useScannerQueue } from '../lib/use-scanner-queue.js'; import { useCameraScanner } from '../lib/use-camera-scanner.js'; import { useScannerIdentification } from '../lib/use-scanner-identification.js'; import { clearScannerCartStorage } from '../lib/scanner-session.js'; import { collectionDisplayName } from '../lib/collection-vocabulary.js'; export default function Scanner() { const { user, loading: authLoading } = useAuth(); const router = useRouter(); const [isCheckoutOpen, setIsCheckoutOpen] = useState(false); const [isListPickerOpen, setIsListPickerOpen] = useState(false); const [showLeaveModal, setShowLeaveModal] = useState(false); const [listCommitError, setListCommitError] = useState(null); const verificationPausedRef = useRef(false); const { scanDefaults } = useScannerSession(); const queue = useScannerQueue({ user, scanDefaults, deckMode: null }); const onVerifyCardRef = useRef(null); const camera = useCameraScanner({ onError: (msg) => console.error('Camera error:', msg), onVerifyCard: (cardTracker) => onVerifyCardRef.current?.(cardTracker), verificationPausedRef, }); const identification = useScannerIdentification({ onCardScanned: queue.handleCardScanned, onError: (msg) => console.error('Identification error:', msg), videoRef: camera.videoRef, canvasRef: camera.canvasRef, onVerifyCardRef, verificationPausedRef, }); const unprocessedCount = queue.unprocessedCount; useEffect(() => { if (!authLoading && !user) { router.push(`/login?returnUrl=${encodeURIComponent('/scanner')}`); } }, [authLoading, user, router]); useEffect(() => { const mobileCheckoutPauses = typeof window !== 'undefined' && window.matchMedia('(max-width: 767px)').matches && isCheckoutOpen; verificationPausedRef.current = mobileCheckoutPauses || isListPickerOpen || Boolean(identification.disambiguation); }, [isCheckoutOpen, isListPickerOpen, identification.disambiguation]); const handleLeaveConfirm = () => { clearScannerCartStorage(); queue.clearScannedCards(); setShowLeaveModal(false); router.back(); }; const handleListPick = async (collectionId) => { setListCommitError(null); const selectedIds = queue.scannedCards .filter((card) => queue.selectedCards.has(card.id)) .map((card) => card.id); if (selectedIds.length === 0) return; const successfulIds = await queue.commitSelectedToCollection(collectionId); if (!successfulIds?.length) { setListCommitError('Could not add cards to the list. Try again.'); return; } setIsListPickerOpen(false); }; if (authLoading) { return (
); } if (!user) { return null; } return (
unprocessedCount > 0 ? setShowLeaveModal(true) : router.back() } onOpenCheckout={() => setIsCheckoutOpen(true)} onGalleryIdentify={(file) => identification.identifyFromGalleryFile(file)} latestPeekCard={queue.scannedCards[0] ?? null} cartCount={unprocessedCount} isCheckoutOpen={isCheckoutOpen} verificationPausedRef={verificationPausedRef} />
{isCheckoutOpen && ( setIsCheckoutOpen(false)} onOpenListPicker={() => setIsListPickerOpen(true)} trapActive={!isListPickerOpen} /> )}
setIsListPickerOpen(true)} />
setShowLeaveModal(false)} title="Leave scanner?" description={`${unprocessedCount} scanned ${unprocessedCount === 1 ? 'card' : 'cards'} haven't been added yet. Leaving will clear your cart.`} >
{ setIsListPickerOpen(false); setListCommitError(null); }} title="Choose a List" description="Add the selected cards to one of your lists." > {listCommitError && (
{listCommitError}
)}
    {queue.collections.map((collection) => (
  • ))} {queue.collections.length === 0 && (

    No lists yet. Create a list from the Lists page first.

    )}
); }