From 484bd02f9a1ef5af1437877230166671fee0eeb9 Mon Sep 17 00:00:00 2001 From: varutasu <104105839+varutasu@users.noreply.github.com> Date: Fri, 14 Aug 2026 21:42:59 -0500 Subject: [PATCH] Polish scanner checkout glass surfaces and remove dead code. (#161) Align toast, sheet, and Review N pill with GlassSurface tokens, use solid cart rows to avoid stacked blurs, and delete pre-rebuild scanner components no longer referenced by /scanner. Co-authored-by: Cursor --- .convoys/scanner-mobile-checkout.md | 2 +- components/CameraScanner.js | 44 --- components/CameraScannerView.js | 251 -------------- components/ScannerPageView.js | 327 ------------------ components/scanner/DeckModeIndicator.js | 51 --- components/scanner/ReviewCardItem.js | 19 +- components/scanner/ScannerCheckoutSheet.js | 13 +- components/scanner/ScannerCountPill.js | 11 +- components/scanner/ScannerSetup.js | 379 --------------------- components/scanner/ScannerToast.js | 20 +- lib/use-focus-trap.js | 2 +- lib/use-scanner-session.js | 23 -- 12 files changed, 42 insertions(+), 1100 deletions(-) delete mode 100644 components/CameraScanner.js delete mode 100644 components/CameraScannerView.js delete mode 100644 components/ScannerPageView.js delete mode 100644 components/scanner/DeckModeIndicator.js delete mode 100644 components/scanner/ScannerSetup.js diff --git a/.convoys/scanner-mobile-checkout.md b/.convoys/scanner-mobile-checkout.md index 9686245..3299157 100644 --- a/.convoys/scanner-mobile-checkout.md +++ b/.convoys/scanner-mobile-checkout.md @@ -7,7 +7,7 @@ success_metric: | the user can open a checkout sheet, select cards, and commit them to My Collection or a List without leaving the session. skip: [] -status: open +status: shipped created: 2026-08-14 depends_on: - scanner-rebuild diff --git a/components/CameraScanner.js b/components/CameraScanner.js deleted file mode 100644 index 885018a..0000000 --- a/components/CameraScanner.js +++ /dev/null @@ -1,44 +0,0 @@ -import { useRef } from 'react'; -import { useCameraScanner } from '../lib/use-camera-scanner.js'; -import { useScannerIdentification } from '../lib/use-scanner-identification.js'; -import CameraScannerView from './CameraScannerView.js'; - -export default function CameraScanner({ onCardScanned, onError }) { - const verificationPausedRef = useRef(false); - const onVerifyCardRef = useRef(() => {}); - - const camera = useCameraScanner({ - onError, - verificationPausedRef, - onVerifyCard: (card) => onVerifyCardRef.current(card), - }); - - const identification = useScannerIdentification({ - onCardScanned, - onError, - videoRef: camera.videoRef, - canvasRef: camera.canvasRef, - onVerifyCardRef, - verificationPausedRef, - }); - - return ( - - ); -} diff --git a/components/CameraScannerView.js b/components/CameraScannerView.js deleted file mode 100644 index 0ff38a1..0000000 --- a/components/CameraScannerView.js +++ /dev/null @@ -1,251 +0,0 @@ -import ScanDisambiguationDialog from './ScanDisambiguationDialog.js'; - -const CONFIRMED_COLOR = '#10B981'; -const SCANNED_COLOR = '#3B82F6'; - -function overlayBorderColor(status) { - if (status === 'scanned') return SCANNED_COLOR; - return CONFIRMED_COLOR; -} - -function overlayGlowColor(status) { - if (status === 'scanned') return `${SCANNED_COLOR}50`; - return `${CONFIRMED_COLOR}50`; -} - -export default function CameraScannerView({ - videoRef, - canvasRef, - detectionCanvasRef, - isStreaming, - isDetecting, - trackedCards, - videoMetrics, - startCamera, - stopCamera, - scanNotice, - disambiguation, - submittingReview, - onPick, - onNotInCatalog, - onCancelDisambiguation, -}) { - const foundCards = trackedCards.filter( - (card) => card.status === 'confirmed' || card.status === 'scanned' - ); - const foundCardCount = foundCards.length; - - return ( -
- {scanNotice && ( -
- {scanNotice} -
- )} -
-
- - - - - {isStreaming && ( -
-
-
- 🎯 -
-

- Smart Detection Active -

-
-
-
- ● - Shape recognition -
-
- ● - Server identification -
-
- ● - Position tracking -
-
- ● - Database lookup -
-
-
- )} - - -
- ); -} diff --git a/components/ScannerPageView.js b/components/ScannerPageView.js deleted file mode 100644 index 3559730..0000000 --- a/components/ScannerPageView.js +++ /dev/null @@ -1,327 +0,0 @@ -import CameraScanner from './CameraScanner'; -import ScannerDestinationPicker from './ScannerDestinationPicker'; -import ScannedCardItem, { CONDITION_OPTIONS } from './ScannedCardItem'; -import OCRSettings from './OCRSettings'; -import { Modal, Input, Button } from './ui'; -import { VOCAB } from '../lib/collection-vocabulary.js'; - -export default function ScannerPageView({ - gameFilter, - onGameFilterChange, - sessionDestination, - onDestinationChange, - scanDefaults, - onScanDefaultsChange, - queue, - showOCRSettings, - onOpenOCRSettings, - onCloseOCRSettings, - onScannerError, -}) { - - return ( -
-
-

- πŸƒ Card Scanner -

-

- Pick a destination once β€” every scan lands there until you change it -

-
- - - - {queue.autoRouteError && ( -
- {queue.autoRouteError} -
- )} - -
-
-

- Defaults for new scans -

-

- Applied to each card when it enters the queue -

-
- - -
- -
-
-
-
-

- Camera Scanner -

- -
- -
- -
-
-
- -
-
-
-

- Scanned Cards -

-
-
- {queue.scannedCards.length} cards -
- {queue.scannedCards.length > 0 && ( - - )} -
-
- -
- {queue.scannedCards.length === 0 ? ( -
- -
No cards scanned yet
-
Start scanning to see cards here
-
- ) : ( -
    - {queue.scannedCards.map((card) => ( -
  • - queue.toggleCardSelection(card.id)} - onIncrement={() => queue.incrementCardQuantity(card.id)} - onDecrement={() => queue.decrementCardQuantity(card.id)} - onUpdateMetadata={(patch) => queue.updateCardMetadata(card.id, patch)} - onMarkOwned={() => queue.addSingleCardToOwned(card)} - onAddToCollection={(collectionId) => queue.addSingleCardToCollection(card, collectionId)} - onAddToDeck={(deckId) => queue.addSingleCardToDeck(card, deckId)} - onRemove={() => queue.removeScannedCard(card.id)} - isAdding={queue.addingCardIds.has(card.id)} - /> -
  • - ))} -
- )} -
-
-
-
- - {queue.selectedCards.size > 0 && ( -
-
-
-
- {queue.selectedCards.size} -
- - {queue.selectedCards.size === 1 ? 'card selected' : 'cards selected'} - -
- -
- -
- - - {queue.collections.length > 0 && ( - - )} - - {queue.decks.length > 0 && ( - - )} -
- -
- - -
-
- )} - - queue.setShowCreateCollection(false)} - title="Create New List" - size="md" - > - queue.setNewCollectionName(e.target.value)} - onKeyPress={(e) => { - if (e.key === 'Enter') { - queue.createCollection(); - } - }} - className="mb-4" - /> -
- - -
-
- - {showOCRSettings && } -
- ); -} diff --git a/components/scanner/DeckModeIndicator.js b/components/scanner/DeckModeIndicator.js deleted file mode 100644 index 34b1921..0000000 --- a/components/scanner/DeckModeIndicator.js +++ /dev/null @@ -1,51 +0,0 @@ -export default function DeckModeIndicator({ current, target, game }) { - const progress = target > 0 ? Math.min(current / target, 1) : 0; - const isComplete = current >= target; - - return ( -
- {/* Progress track */} -
-
-
- - {/* Labels */} -
- - {isComplete ? 'Deck complete!' : `${current}/${target} cards`} - - - {game} - -
-
- ); -} diff --git a/components/scanner/ReviewCardItem.js b/components/scanner/ReviewCardItem.js index 521742d..0d94186 100644 --- a/components/scanner/ReviewCardItem.js +++ b/components/scanner/ReviewCardItem.js @@ -1,6 +1,7 @@ /* eslint-disable @next/next/no-img-element -- External card image URLs; next/image migration is out of scope. */ import { useEffect, useRef, useState } from 'react'; import { formatProcessedDestination, VOCAB } from '../../lib/collection-vocabulary.js'; +import GlassSurface from '../ui/GlassSurface.js'; const CONDITION_OPTIONS = ['NM', 'LP', 'MP', 'HP', 'DMG']; @@ -61,9 +62,11 @@ export default function ReviewCardItem({ return (
@@ -158,10 +161,14 @@ export default function ReviewCardItem({ {menuOpen && ( -
-
+ )}
) : !card.processed ? ( diff --git a/components/scanner/ScannerCheckoutSheet.js b/components/scanner/ScannerCheckoutSheet.js index d99a252..dc0083c 100644 --- a/components/scanner/ScannerCheckoutSheet.js +++ b/components/scanner/ScannerCheckoutSheet.js @@ -2,6 +2,7 @@ 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) { @@ -20,8 +21,9 @@ function CheckoutFooter({ return (
-
-
+