Skip to content

Scan Bottle to Add - Missing Implementation Analysis

Scan Bottle to Add - Missing Implementation Analysis

Section titled “Scan Bottle to Add - Missing Implementation Analysis”

Date: 2026-01-30
Story: Scan Bottle to Add to Inventory
Status: ⚠️ Partially Implemented - Core flow works but barcode type handling is incomplete

The barcode scanning flow for adding products to inventory is functionally working but has a critical gap in barcode type handling. The scanner receives barcode type information but it’s not captured, mapped, or stored according to the domain model’s ProductBarcode structure.

CriteriaStatusNotes
✅ I can use my device’s camera to scan a product barcodeCompleteBarcodeScanner component fully functional
✅ The system sends the barcode to an external product databaseCompleteUPCLookupService with Open Food Facts + UPCitemdb
✅ If the product is found, the system pre-fills Name, Brand, Type, and VolumeCompletebuildProductUpdates function populates all fields
✅ I can review and edit the pre-filled informationCompleteForm fields are fully editable
✅ After confirmation, the new product is added to my inventoryCompletehandleSubmit creates product via GraphQL mutation
❌ Barcode type is captured and storedMissingType is lost during scan callback
❌ Barcode stored as ProductBarcode objectMissingCurrently stored as string only
  • Location: shaker/components/BarcodeScanner.tsx
  • Status: Fully functional
  • Features:
    • Camera permissions handling
    • Multiple barcode type support (UPC, EAN, QR, CODE128)
    • Visual scanning overlay
    • Rescan functionality
    • Error handling
  • Location: shaker/services/upcLookup.ts
  • Status: Fully functional
  • Features:
    • Open Food Facts integration (primary)
    • UPCitemdb fallback
    • 10-second timeout protection
    • Product categorization
    • Error handling with graceful degradation
  • Location: shaker/lib/inventory/add-product/formHelpers.ts
  • Function: buildProductUpdates()
  • Status: Fully functional
  • Populates:
    • Name
    • Brand
    • Type (productCategory)
    • Category
    • Volume (parsed from string)
    • Unit
    • Alcohol Content
    • Image URL
    • Description
  • Location: shaker/app/(tabs)/inventory/add-product.tsx
  • Status: Fully functional
  • Features:
    • All fields editable
    • Validation with error messages
    • Scan success indicator
    • Form state management
  • Location: shaker/app/(tabs)/inventory/add-product.tsx
  • GraphQL Mutation: CreateProduct.graphql
  • Status: Fully functional
  • Features:
    • Form validation
    • Mutation execution
    • Success/error handling
    • Form reset after success

Issue: The BarcodeScanner component receives { type, data } from expo-camera’s BarcodeScanningResult, but only passes the data (barcode string) to the callback. The type information is discarded.

Current Implementation:

// shaker/components/BarcodeScanner.tsx:39
const handleBarCodeScanned = async ({ type, data }: BarcodeScanningResult) => {
// ...
onBarcodeScanned(data, result.product); // ❌ 'type' is lost here
};

Required Fix:

// Should pass both barcode code and type
onBarcodeScanned({ code: data, type: mapBarcodeType(type) }, result.product);

Issue: expo-camera returns barcode types in a different format than the domain model expects:

  • expo-camera types: 'upc_a', 'upc_e', 'ean13', 'ean8', 'qr', 'code128', 'code39', etc.
  • ProductBarcode types: 'UPC' | 'EAN' | 'QR' | 'CODE128'

Missing: A mapping function to convert expo-camera barcode types to BarcodeType.

Required Implementation:

// shaker/utils/barcodeMapping.ts (NEW FILE)
export function mapExpoBarcodeTypeToProductBarcodeType(
expoType: string
): BarcodeType {
// Map expo-camera types to ProductBarcode types
if (expoType.startsWith("upc_")) return "UPC";
if (expoType.startsWith("ean")) return "EAN";
if (expoType === "qr") return "QR";
if (expoType === "code128") return "CODE128";
// Default fallback
return "UPC";
}

Issue: The form currently stores barcode as a string (upc: string) instead of a ProductBarcode object.

Current Structure:

// shaker/lib/inventory/add-product/formTypes.ts:38
export interface FormData {
// ...
upc: string; // ❌ Should be ProductBarcode object
// ...
}

Required Structure:

export interface FormData {
// ...
barcode?: {
code: string;
type: BarcodeType;
scannedDate?: string;
};
// ...
}

Issue: The prepareMutationData function passes barcode as a string instead of a ProductBarcode object.

Current Implementation:

// shaker/lib/inventory/add-product/formValidation.ts:104
barcode: formData.upc || undefined, // ❌ Just a string

Required Implementation:

barcode: formData.barcode
? {
code: formData.barcode.code,
type: formData.barcode.type,
scannedDate: formData.barcode.scannedDate,
}
: undefined,

Issue: The ProductBarcode interface includes scannedDate?: string, but this is never set when a barcode is scanned.

Required Fix:

// When barcode is scanned, set scannedDate
barcode: {
code: data,
type: mappedType,
scannedDate: new Date().toISOString(), // ✅ Set when scanned
}

Issue: Users can manually enter a barcode in the form, but there’s no way to specify the barcode type for manual entries.

Required Enhancement:

  • Add a picker/dropdown for barcode type when manually entering barcodes
  • Default to ‘UPC’ if not specified
  • Validate barcode format based on selected type
  1. Create barcode mapping utility (shaker/utils/barcodeMapping.ts)

    • Function to map expo-camera types to ProductBarcode types
    • Unit tests for type mapping
  2. Update BarcodeScanner component

    • Modify callback to pass { code, type } instead of just string
    • Update callback signature to accept ProductBarcode object
    • Set scannedDate when scanning
  1. Update FormData interface

    • Change upc: string to barcode?: ProductBarcode
    • Update initial form data
    • Update all form field handlers
  2. Update buildProductUpdates function

    • Accept ProductBarcode object instead of string
    • Handle barcode object properly
  3. Update form UI

    • Update barcode input field to show both code and type
    • Add barcode type selector for manual entries
    • Update display labels
  1. Update prepareMutationData function

    • Format barcode as ProductBarcode object for mutation
    • Handle optional barcode field
  2. Verify GraphQL Schema

    • Ensure CreateProductInput accepts ProductBarcode structure
    • Update mutation if needed
    • Update GraphQL fragment to include barcode fields
  1. Update existing tests

    • Fix tests that use old upc: string format
    • Add tests for barcode type mapping
    • Test manual barcode entry with type selection
  2. Integration testing

    • Test full flow: scan → pre-fill → edit → save
    • Test manual barcode entry
    • Verify barcode is saved correctly in backend
  1. shaker/components/BarcodeScanner.tsx

    • Update onBarcodeScanned callback signature
    • Pass barcode type and set scannedDate
  2. shaker/lib/inventory/add-product/formTypes.ts

    • Change upc: string to barcode?: ProductBarcode
  3. shaker/lib/inventory/add-product/formHelpers.ts

    • Update buildProductUpdates to accept ProductBarcode
    • Update form initialization
  4. shaker/lib/inventory/add-product/formValidation.ts

    • Update prepareMutationData to format barcode correctly
  5. shaker/app/(tabs)/inventory/add-product.tsx

    • Update form handlers for barcode object
    • Add barcode type selector UI
    • Update barcode display
  1. shaker/utils/barcodeMapping.ts (NEW)

    • Barcode type mapping function
    • Type conversion utilities
  2. shaker/utils/__tests__/barcodeMapping.test.ts (NEW)

    • Unit tests for barcode mapping
  • Low Risk: Changes are primarily internal to form handling
  • Backward Compatible: Existing products without barcode type will still work
  • ⚠️ Migration Needed: Existing products with upc string should be migrated to barcode object structure
  • No External Dependencies: All changes use existing types and utilities
  • GraphQL Schema: May need backend schema update if ProductBarcode input type differs from current implementation
  • Unit Tests: Barcode type mapping utility
  • Component Tests: BarcodeScanner callback updates
  • Integration Tests: Full scan → save flow
  • Migration Tests: Handle existing products with old format
  1. Review & Approval: Get approval for implementation plan
  2. Implementation: Start with Phase 1 (barcode type capture & mapping)
  3. Testing: Comprehensive testing of changes
  4. Documentation: Update user guides if UI changes
  5. Migration: Plan for migrating existing products with old format

Last Updated: 2026-01-30
Review Status:IMPLEMENTATION COMPLETE
Priority: Medium (Functionality works, but type handling should be fixed for data integrity)

All phases complete - Implementation finished on 2026-01-30

  1. Created barcode type mapping utility (shaker/utils/barcodeMapping.ts)

    • Maps expo-camera types to ProductBarcode types
    • Includes validation and display label helpers
  2. Updated BarcodeScanner component

    • Now captures and passes ProductBarcode object with type and scannedDate
    • Updated callback signature to accept ProductBarcode instead of string
  3. Updated FormData interface

    • Changed from upc: string to barcode?: ProductBarcode
    • Updated initial form data
  4. Updated buildProductUpdates function

    • Now accepts ProductBarcode object instead of string
    • Properly handles barcode structure
  5. Updated form UI

    • Added barcode code input field
    • Added barcode type selector for manual entries
    • Displays scanned date when available
  6. Updated prepareMutationData

    • Formats barcode as ProductBarcode object for mutation
    • Handles optional barcode field correctly
  7. Updated all related components

    • add-product.tsx - Full ProductBarcode support
    • quick-update.tsx - Updated to use ProductBarcode
    • edit-product.tsx - Updated to display ProductBarcode
    • ProductScannerDemo.tsx - Updated to use ProductBarcode

New Files:

  • shaker/utils/barcodeMapping.ts - Barcode type mapping utility
  • shaker/utils/__tests__/barcodeMapping.test.ts - Unit tests (57 tests)
  • docs-site/docs/implementation/graphql-barcode-schema.md - GraphQL schema documentation

Modified Files:

  • shaker/components/BarcodeScanner.tsx - Updated to pass ProductBarcode object
  • shaker/lib/inventory/add-product/formTypes.ts - Updated FormData interface
  • shaker/lib/inventory/add-product/formHelpers.ts - Updated buildProductUpdates
  • shaker/lib/inventory/add-product/formValidation.ts - Updated prepareMutationData
  • shaker/app/(tabs)/inventory/add-product.tsx - Updated form UI and handlers
  • shaker/app/(tabs)/inventory/quick-update.tsx - Updated to use ProductBarcode
  • shaker/app/(tabs)/inventory/products/edit-product.tsx - Updated to display ProductBarcode
  • shaker/components/ProductScannerDemo.tsx - Updated to use ProductBarcode
  • shaker/graphql/mutations/CreateProduct.graphql - Added barcode to response

Linting: All files pass linting with no errors
Unit Tests: Barcode mapping utility fully tested (57 tests, all passing)
Integration Tests: Full scan → save flow needs testing
Manual Testing: Requires testing on device with actual barcode scanning

  1. Add unit tests for barcodeMapping.ts utility - COMPLETE (57 tests, all passing)
  2. Update CreateProduct mutation to return barcode - COMPLETE (mutation updated)
  3. Document GraphQL schema requirements - COMPLETE (see GraphQL Barcode Schema)
  4. ⏳ Verify GraphQL mutation accepts ProductBarcode structure correctly (backend verification needed)
  5. ⏳ Test barcode scanning on actual device with various barcode types
  6. ⏳ Update user documentation if UI changes are significant

Unit Tests: shaker/utils/__tests__/barcodeMapping.test.ts

  • mapExpoBarcodeTypeToProductBarcodeType - 28 tests

    • UPC variants (6 tests)
    • EAN variants (6 tests)
    • QR code variants (5 tests)
    • CODE128 variants (5 tests)
    • Unknown types and edge cases (6 tests)
  • getBarcodeTypeLabel - 5 tests

    • All valid BarcodeType values with correct labels
  • validateBarcodeFormat - 24 tests

    • Numeric types (UPC, EAN, CODE128) validation (12 tests)
    • QR code validation (10 tests)
    • Edge cases (2 tests)

Test Results: All 57 tests passing ✅