import { useState, useEffect } from 'react'; import { aiCardOCR, ollamaCardOCR, geminiCardOCR } from '../lib/ai-ocr'; export default function OCRSettings({ isOpen, onClose }) { const [settings, setSettings] = useState({ service: 'gemini', // Default to free Gemini openaiApiKey: '', geminiApiKey: '', ollamaUrl: 'http://localhost:11434' }); const [isTesting, setIsTesting] = useState(false); const [testResult, setTestResult] = useState(null); // Load settings from localStorage on mount useEffect(() => { const loadSettings = async () => { const savedSettings = localStorage.getItem('ocrSettings'); let currentSettings = { service: 'gemini', openaiApiKey: '', geminiApiKey: '', ollamaUrl: 'http://localhost:11434' }; if (savedSettings) { try { const parsed = JSON.parse(savedSettings); currentSettings = { ...currentSettings, ...parsed }; } catch (error) { console.error('Error loading OCR settings:', error); } } // Try to auto-load Gemini API key from environment if not already set if (!currentSettings.geminiApiKey) { try { const response = await fetch('/api/config/gemini'); if (response.ok) { const data = await response.json(); if (data.hasKey && data.apiKey) { currentSettings.geminiApiKey = data.apiKey; currentSettings.service = 'gemini'; // Default to Gemini if key is available } } } catch (error) { console.log('Could not auto-load Gemini API key:', error); } } setSettings(currentSettings); }; loadSettings(); }, []); const saveSettings = () => { try { localStorage.setItem('ocrSettings', JSON.stringify(settings)); // Configure AI services if (settings.openaiApiKey) { aiCardOCR.setApiKey(settings.openaiApiKey); } if (settings.geminiApiKey) { geminiCardOCR.setApiKey(settings.geminiApiKey); } if (settings.ollamaUrl) { ollamaCardOCR.setBaseUrl(settings.ollamaUrl); } setTestResult({ type: 'success', message: 'Settings saved successfully!' }); setTimeout(() => setTestResult(null), 3000); } catch (error) { console.error('Error saving OCR settings:', error); setTestResult({ type: 'error', message: 'Failed to save settings' }); } }; const testConnection = async () => { setIsTesting(true); setTestResult(null); try { if (settings.service === 'puter') { // Test Puter.js connection try { // Try to load Puter.js if not already loaded if (typeof window !== 'undefined' && !window.puter) { const script = document.createElement('script'); script.src = 'https://js.puter.com/v2/'; await new Promise((resolve, reject) => { script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); } if (window.puter && window.puter.ai) { setTestResult({ type: 'success', message: 'Puter.js loaded successfully! Ready for free AI vision.' }); } else { setTestResult({ type: 'error', message: 'Failed to load Puter.js AI capabilities' }); } } catch (error) { setTestResult({ type: 'error', message: 'Could not connect to Puter.js service' }); } } else if (settings.service === 'openai') { if (!settings.openaiApiKey) { setTestResult({ type: 'error', message: 'Please enter your OpenAI API key' }); return; } // Test with a simple request const response = await fetch('https://api.openai.com/v1/models', { headers: { 'Authorization': `Bearer ${settings.openaiApiKey}`, } }); if (response.ok) { setTestResult({ type: 'success', message: 'OpenAI API connection successful!' }); } else { const error = await response.json().catch(() => ({})); setTestResult({ type: 'error', message: `OpenAI API error: ${error.error?.message || response.statusText}` }); } } else if (settings.service === 'gemini') { if (!settings.geminiApiKey) { setTestResult({ type: 'error', message: 'Please enter your Gemini API key' }); return; } // Test with a simple request const response = await fetch('https://generativelanguage.googleapis.com/v1beta/models', { headers: { 'x-goog-api-key': settings.geminiApiKey, } }); if (response.ok) { const data = await response.json(); const hasVisionModel = data.models?.some(model => model.name.includes('gemini') && model.supportedGenerationMethods?.includes('generateContent') ); if (hasVisionModel) { setTestResult({ type: 'success', message: 'Gemini API connection successful with vision support!' }); } else { setTestResult({ type: 'warning', message: 'Gemini connected but vision capabilities unclear.' }); } } else { const error = await response.json().catch(() => ({})); setTestResult({ type: 'error', message: `Gemini API error: ${error.error?.message || response.statusText}` }); } } else if (settings.service === 'ollama') { // Test Ollama connection const response = await fetch(`${settings.ollamaUrl}/api/tags`); if (response.ok) { const data = await response.json(); const hasVisionModel = data.models?.some(model => model.name.includes('llava') || model.name.includes('vision') ); if (hasVisionModel) { setTestResult({ type: 'success', message: 'Ollama connection successful with vision models!' }); } else { setTestResult({ type: 'warning', message: 'Ollama connected but no vision models found. Install llava:latest for card scanning.' }); } } else { setTestResult({ type: 'error', message: 'Could not connect to Ollama server' }); } } } catch (error) { console.error('Connection test error:', error); setTestResult({ type: 'error', message: `Connection failed: ${error.message}` }); } finally { setIsTesting(false); } }; const handleInputChange = (field, value) => { setSettings(prev => ({ ...prev, [field]: value })); setTestResult(null); }; if (!isOpen) return null; return (
{/* Header */}

🤖 OCR Settings

{/* Content */}
{/* Service Selection */}
{/* OpenAI Settings */} {settings.service === 'openai' && (
handleInputChange('openaiApiKey', e.target.value)} className="w-full px-3 py-2 rounded-lg border" style={{ backgroundColor: 'var(--bg-primary)', borderColor: 'var(--border)', color: 'var(--text-primary)' }} />
Get your API key from{' '} OpenAI Platform
)} {/* Gemini Settings */} {settings.service === 'gemini' && (
handleInputChange('geminiApiKey', e.target.value)} className="w-full px-3 py-2 rounded-lg border" style={{ backgroundColor: 'var(--bg-primary)', borderColor: 'var(--border)', color: 'var(--text-primary)' }} />
Get your free API key from{' '} Google AI Studio
)} {/* Ollama Settings */} {settings.service === 'ollama' && (
handleInputChange('ollamaUrl', e.target.value)} className="w-full px-3 py-2 rounded-lg border" style={{ backgroundColor: 'var(--bg-primary)', borderColor: 'var(--border)', color: 'var(--text-primary)' }} />
Install Ollama and run: ollama pull llava:latest
Setup guide:{' '} ollama.ai
)} {/* Test Result */} {testResult && (
{testResult.message}
)} {/* Actions */}
{/* Usage Tips */}
💡 Tips
  • • Puter.js offers free GPT-4o vision with no setup required
  • • OpenAI Vision API offers highest accuracy for card recognition
  • • Ollama is free and private but requires local setup
  • • Test your connection before scanning cards
  • • Settings are saved locally in your browser
); }