Files
pantry/app/pages/scan.vue
Pantry Lead Agent 7d35a3e7b3
Some checks failed
Deploy to Coolify / Run Tests (pull_request) Has been cancelled
Deploy to Coolify / Deploy to Development (pull_request) Has been cancelled
Deploy to Coolify / Deploy to Production (pull_request) Has been cancelled
Deploy to Coolify / Deploy to Test (pull_request) Has been cancelled
Pull Request Checks / Validate PR (pull_request) Has been cancelled
Deploy to Coolify / Code Quality (pull_request) Has been cancelled
feat: implement scan-to-add flow (#25)
- Create useProductLookup composable
- Integrate real product lookup in scan page
- Add query parameter handling in index.vue
- Pre-fill AddItemForm from scan data
- Parse quantity and unit from product data
- Include barcode and brand in notes

Complete end-to-end scan workflow:
1. Scan barcode
2. Fetch from Open Food Facts
3. Navigate to inventory with data
4. Pre-filled add form
5. One-click add to inventory

Closes #25
2026-02-24 00:04:10 +00:00

113 lines
3.0 KiB
Vue

<template>
<div>
<h1 class="text-3xl font-bold text-gray-900 mb-6">Scan Item</h1>
<UCard v-if="!scannedBarcode" class="mb-6">
<ScanBarcodeScanner
@barcode-detected="handleBarcodeDetected"
@manual-entry="showManualEntry = true"
/>
</UCard>
<!-- Product Lookup Result -->
<UCard v-if="productData" class="mb-6">
<div class="space-y-4">
<div class="flex items-start gap-4">
<img
v-if="productData.image_url"
:src="productData.image_url"
:alt="productData.name"
class="w-24 h-24 object-cover rounded"
/>
<div class="flex-1">
<h3 class="text-xl font-bold mb-1">{{ productData.name }}</h3>
<p v-if="productData.brand" class="text-gray-600">{{ productData.brand }}</p>
<p class="text-sm text-gray-500 mt-2">Barcode: {{ scannedBarcode }}</p>
</div>
</div>
<UAlert
v-if="lookupError"
color="yellow"
icon="i-heroicons-exclamation-triangle"
title="Product not found"
:description="lookupError"
/>
<div class="flex gap-2">
<UButton
color="primary"
size="lg"
icon="i-heroicons-plus"
class="flex-1"
@click="addToInventory"
>
Add to Inventory
</UButton>
<UButton
color="gray"
size="lg"
@click="resetScanner"
>
Scan Again
</UButton>
</div>
</div>
</UCard>
<!-- Loading State -->
<UCard v-if="isLookingUp">
<div class="text-center py-8">
<div class="inline-block animate-spin rounded-full h-12 w-12 border-b-2 border-primary-500 mb-4"></div>
<p class="text-gray-600">Looking up product...</p>
</div>
</UCard>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'default'
})
const scannedBarcode = ref<string | null>(null)
const productData = ref<any>(null)
const showManualEntry = ref(false)
// Use product lookup composable
const { lookupProduct, isLoading: isLookingUp, error: lookupError } = useProductLookup()
const handleBarcodeDetected = async (barcode: string) => {
scannedBarcode.value = barcode
// Fetch product data from Edge Function
const data = await lookupProduct(barcode)
if (data) {
productData.value = data
}
}
const addToInventory = () => {
// Navigate to home page with add form open and pre-filled
navigateTo({
path: '/',
query: {
action: 'add',
barcode: scannedBarcode.value,
name: productData.value?.name || undefined,
brand: productData.value?.brand || undefined,
image_url: productData.value?.image_url || undefined,
quantity: productData.value?.quantity || undefined
}
})
}
const resetScanner = () => {
scannedBarcode.value = null
productData.value = null
lookupError.value = null
isLookingUp.value = false
}
</script>