import React, { useState, useCallback } from 'react'; import { AnalysisType, FlyerItem, Store } from '../types'; import { getQuickInsights, getDeepDiveAnalysis, searchWeb, planTripWithMaps, generateImageFromText } from '../services/geminiService'; import { LoadingSpinner } from './LoadingSpinner'; import { LightbulbIcon } from './icons/LightbulbIcon'; import { BrainIcon } from './icons/BrainIcon'; import { SearchIcon } from './icons/SearchIcon'; import { MapPinIcon } from './icons/MapPinIcon'; import { PhotoIcon } from './icons/PhotoIcon'; interface AnalysisPanelProps { flyerItems: FlyerItem[]; store?: Store; } interface TabButtonProps { label: string; icon: React.ReactNode; isActive: boolean; onClick: () => void; } const TabButton: React.FC = ({ label, icon, isActive, onClick }) => { const activeClasses = 'bg-brand-primary text-white'; const inactiveClasses = 'bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-300 dark:hover:bg-gray-600'; return ( ); }; export const AnalysisPanel: React.FC = ({ flyerItems, store }) => { const [activeTab, setActiveTab] = useState(AnalysisType.QUICK_INSIGHTS); const [results, setResults] = useState<{ [key in AnalysisType]?: string }>({}); const [sources, setSources] = useState([]); const [loadingStates, setLoadingStates] = useState<{ [key in AnalysisType]?: boolean }>({}); const [error, setError] = useState(null); // State for new feature stubs const [generatedImageUrl, setGeneratedImageUrl] = useState(null); const [isGeneratingImage, setIsGeneratingImage] = useState(false); const handleAnalysis = useCallback(async (type: AnalysisType) => { setLoadingStates(prev => ({ ...prev, [type]: true })); setError(null); try { let responseText = ''; if (type === AnalysisType.QUICK_INSIGHTS) { responseText = await getQuickInsights(flyerItems); } else if (type === AnalysisType.DEEP_DIVE) { responseText = await getDeepDiveAnalysis(flyerItems); } else if (type === AnalysisType.WEB_SEARCH) { const { text, sources } = await searchWeb(flyerItems); responseText = text; setSources(sources); } else if (type === AnalysisType.PLAN_TRIP) { const userLocation = await new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition( (position) => resolve(position.coords), (error) => reject(error) ); }); const { text, sources } = await planTripWithMaps(flyerItems, store, userLocation); responseText = text; setSources(sources); } setResults(prev => ({ ...prev, [type]: responseText })); } catch (e: any) { console.error(`Analysis failed for type ${type}:`, e); const userFriendlyMessage = e.code === 1 ? "Please allow location access to use this feature." : `Failed to get ${type.replace('_', ' ')}. Please try again.`; setError(userFriendlyMessage); } finally { setLoadingStates(prev => ({ ...prev, [type]: false })); } }, [flyerItems, store]); const handleGenerateImage = useCallback(async () => { const mealPlanText = results[AnalysisType.DEEP_DIVE]; if (!mealPlanText) return; setIsGeneratingImage(true); try { const base64Image = await generateImageFromText(mealPlanText); setGeneratedImageUrl(`data:image/png;base64,${base64Image}`); } catch (e: any) { setError(`Failed to generate image: ${e.message}`); } finally { setIsGeneratingImage(false); } }, [results]); const renderContent = () => { if (loadingStates[activeTab]) { return
; } const resultText = results[activeTab]; if (resultText) { const isSearchType = activeTab === AnalysisType.WEB_SEARCH || activeTab === AnalysisType.PLAN_TRIP; return (
{resultText} {isSearchType && sources.length > 0 && (

Sources:

    {sources.map((source, index) => { const uri = source.web?.uri || source.maps?.uri; const title = source.web?.title || source.maps?.title || 'Map Link'; if (!uri) return null; return (
  • {title}
  • ) })}
)} {activeTab === AnalysisType.DEEP_DIVE && (
{generatedImageUrl ? ( AI generated meal plan ) : ( )}
)}
); } return (

Click below to generate AI-powered insights.

); }; return (
} isActive={activeTab === AnalysisType.QUICK_INSIGHTS} onClick={() => setActiveTab(AnalysisType.QUICK_INSIGHTS)} /> } isActive={activeTab === AnalysisType.DEEP_DIVE} onClick={() => setActiveTab(AnalysisType.DEEP_DIVE)} /> } isActive={activeTab === AnalysisType.WEB_SEARCH} onClick={() => setActiveTab(AnalysisType.WEB_SEARCH)} /> } isActive={activeTab === AnalysisType.PLAN_TRIP} onClick={() => setActiveTab(AnalysisType.PLAN_TRIP)} />
{error &&

{error}

} {renderContent()}
); };