import React, { useState, useRef } from 'react'; import { ScanIcon, SparklesIcon, UploadCloudIcon, CheckCircleIcon, AlertTriangleIcon } from '../components/icons'; import Spinner from '../components/Spinner'; import { identifyBonsaiSpecies, isAIConfigured } from '../services/geminiService'; import type { View, SpeciesIdentificationResult } from '../types'; import { AppStatus } from '../types'; const SpeciesIdentifierView: React.FC<{ setActiveView: (view: View) => void }> = ({ setActiveView }) => { const [status, setStatus] = useState(AppStatus.IDLE); const [image, setImage] = useState<{ preview: string; base64: string } | null>(null); const [result, setResult] = useState(null); const [error, setError] = useState(''); const fileInputRef = useRef(null); const aiConfigured = isAIConfigured(); const handleFileChange = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { if (file.size > 4 * 1024 * 1024) { // 4MB limit setError("File size exceeds 4MB. Please upload a smaller image."); return; } const reader = new FileReader(); reader.onloadend = () => { const base64String = (reader.result as string).split(',')[1]; setImage({ preview: reader.result as string, base64: base64String }); setError(''); setStatus(AppStatus.IDLE); setResult(null); }; reader.onerror = () => setError("Failed to read the file."); reader.readAsDataURL(file); } }; const handleIdentify = async () => { if (!image) { setError("Please upload an image to identify."); return; } setStatus(AppStatus.ANALYZING); setError(''); setResult(null); try { const idResult = await identifyBonsaiSpecies(image.base64); if (idResult && idResult.identifications.length > 0) { setResult(idResult); setStatus(AppStatus.SUCCESS); } else { throw new Error("Could not identify the species. The AI may be busy, or the image may not be clear enough. Please try a different photo."); } } catch (e: any) { setError(e.message); setStatus(AppStatus.ERROR); } }; const startFullAnalysis = (species: string) => { // A bit of a hack to pass data to another view; for a larger app, a state manager (Context, Redux) would be better. window.sessionStorage.setItem('prefilled-species', species); setActiveView('steward'); } const renderContent = () => { switch (status) { case AppStatus.ANALYZING: return ; case AppStatus.SUCCESS: if (!result) return null; return (

Identification Results

{result.identifications.map((id, index) => (

{id.commonName}

{id.confidence} Confidence

{id.scientificName}

Reasoning: {id.reasoning}

General Care Summary

{id.generalCareSummary}

{id.confidence === 'High' && index === 0 && ( )}
))}
); case AppStatus.ERROR: return

{error}

; case AppStatus.IDLE: default: return (
fileInputRef.current?.click()} className="flex justify-center rounded-lg border-2 border-dashed border-stone-300 px-6 py-10 hover:border-green-600 transition-colors cursor-pointer">
{image ? Bonsai preview : ( <>

Upload a photo to identify

PNG, JPG up to 4MB

)}
{error &&

{error}

} {!aiConfigured && (

AI features are disabled. Please set your Gemini API key in the{' '} .

)}
); } } return (

Species Identifier

Don't know what kind of tree you have? Upload a photo and let our AI identify it for you.

{renderContent()}
); }; export default SpeciesIdentifierView;