'use client'; import { useState, useRef } from 'react'; import { toast } from 'react-hot-toast'; import { Camera, Check, RefreshCw, X, Image as ImageIcon, Sparkles, Hash, Layout, Layers, Package, ChevronDown } from 'lucide-react'; import { inventoryApi } from '@/lib/api'; interface AIOnboardingProps { onCancel: () => void; onComplete: (itemData: any) => void; categories: any[]; inventory: any[]; } export default function AIOnboarding({ onCancel, onComplete, categories, inventory }: AIOnboardingProps) { const [image, setImage] = useState(null); const [uploading, setUploading] = useState(false); const [extractedData, setExtractedData] = useState(null); const [mode, setMode] = useState<'item' | 'box'>('item'); // Extract unique item types for suggestions const existingTypes = Array.from(new Set(inventory.map(i => i.type).filter(Boolean))).sort() as string[]; const existingBoxes = Array.from(new Set(inventory.map(i => i.box_label).filter(Boolean))).sort() as string[]; const cameraInputRef = useRef(null); const fileInputRef = useRef(null); const handleFileChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onload = () => setImage(reader.result as string); reader.readAsDataURL(file); } }; const processImage = async () => { if (!image) return; setUploading(true); try { const blob = await (await fetch(image)).blob(); const formData = new FormData(); formData.append('file', blob, 'label.jpg'); const data = await inventoryApi.analyzeLabel(formData, mode); if (data.error) { toast.error(`AI Error: ${data.error}`); setUploading(false); // Force stop loading state return; } setExtractedData(data); if (mode === 'box') { toast.success(`Box identified: ${data.box_label || data.name}`); } else { toast.success("AI extraction complete!"); } } catch (error) { toast.error("Failed to process image with AI"); console.error(error); } finally { setUploading(false); } }; const confirmOnboarding = async () => { // Sanitize data for the backend (Pydantic validation) const newItem = { name: String(extractedData.name || "New AI Item"), category: String(extractedData.category || "Uncategorized"), type: extractedData.type ? String(extractedData.type) : null, part_number: extractedData.part_number ? String(extractedData.part_number) : null, color: extractedData.color ? String(extractedData.color) : null, specs: String(extractedData.specs || ""), barcode: String(extractedData.barcode || extractedData.part_number || extractedData.serial_number || `AI-${Date.now()}`), quantity: parseFloat(String(extractedData.quantity || 1)), min_quantity: 1.0, box_label: extractedData.box_label ? String(extractedData.box_label) : null, labels_data: JSON.stringify(extractedData) }; onComplete(newItem); }; return (

AI Discovery

Powered by Gemini 2.0 Flash

{!image ? (

{mode === 'box' ? 'Container Discovery Mode' : 'Label Insight Mode'}

{mode === 'box' ? 'Scan the large, prominent label or hand-written name on the container' : 'Scan or upload a sharp photo of the item specifications'}

) : !extractedData ? (
Captured label
{uploading && (

Gemini is processing...

)}
) : (
Validation Mask AI Ready