import React, { useState, useCallback } from 'react'; import { Header } from './components/Header'; import { StepInput } from './components/StepInput'; import { StepStrategy } from './components/StepStrategy'; import { StepReview } from './components/StepReview'; import { StepProcessing } from './components/StepProcessing'; import { StepReport } from './components/StepReport'; import { StepOutreach } from './components/StepOutreach'; import { AppStep, Competitor, AnalysisResult, AnalysisState, Language, SearchStrategy } from './types'; import { identifyCompetitors, analyzeCompanyWithStrategy, generateSearchStrategy } from './services/geminiService'; const generateId = () => Math.random().toString(36).substr(2, 9); const App: React.FC = () => { const [step, setStep] = useState(AppStep.INPUT); const [isLoading, setIsLoading] = useState(false); const [language, setLanguage] = useState('de'); const [referenceUrl, setReferenceUrl] = useState(''); const [targetMarket, setTargetMarket] = useState(''); const [productContext, setProductContext] = useState(''); // Added state for productContext const [referenceCity, setReferenceCity] = useState(''); // Added state for referenceCity const [referenceCountry, setReferenceCountry] = useState(''); // Added state for referenceCountry // Data States const [strategy, setStrategy] = useState(null); const [competitors, setCompetitors] = useState([]); const [categorizedCompetitors, setCategorizedCompetitors] = useState<{ localCompetitors: Competitor[], nationalCompetitors: Competitor[], internationalCompetitors: Competitor[] } | null>(null); // New state for categorized competitors const [analysisResults, setAnalysisResults] = useState([]); const [processingState, setProcessingState] = useState({ currentCompany: '', progress: 0, total: 0, completed: 0 }); const [selectedCompanyForOutreach, setSelectedCompanyForOutreach] = useState(null); const handleBack = () => { if (step === AppStep.STRATEGY) setStep(AppStep.INPUT); else if (step === AppStep.REVIEW_LIST) setStep(AppStep.STRATEGY); else if (step === AppStep.REPORT) setStep(AppStep.REVIEW_LIST); else if (step === AppStep.OUTREACH) { setStep(AppStep.REPORT); setSelectedCompanyForOutreach(null); } }; const handleInitialInput = async (url: string, productCtx: string, market: string, selectedLang: Language) => { setIsLoading(true); setLanguage(selectedLang); setReferenceUrl(url); setTargetMarket(market); setProductContext(productCtx); // Store productContext in state // referenceCity and referenceCountry are not yet extracted from input in StepInput, leaving empty for now. // Future improvement: extract from referenceUrl or add input fields. setReferenceCity(''); setReferenceCountry(''); try { // 1. Generate Strategy first const generatedStrategy = await generateSearchStrategy(url, productCtx, selectedLang); setStrategy(generatedStrategy); setStep(AppStep.STRATEGY); } catch (error) { alert("Failed to generate strategy. Please try again."); console.error(error); } finally { setIsLoading(false); } }; const handleLoadReport = (loadedStrategy: SearchStrategy, loadedResults: AnalysisResult[]) => { setStrategy(loadedStrategy); setAnalysisResults(loadedResults); // Reconstruct competitors list from results for consistency if user goes back const reconstructedCompetitors = loadedResults.map(r => ({ id: generateId(), name: r.companyName, dataSource: r.dataSource })); setCompetitors(reconstructedCompetitors); setStep(AppStep.REPORT); }; const handleStrategyConfirm = async (finalStrategy: SearchStrategy) => { setStrategy(finalStrategy); setIsLoading(true); try { // 2. Identify Competitors based on Reference const idealCustomerProfile = finalStrategy.idealCustomerProfile; // Use ICP for lookalike search const identifiedCompetitors = await identifyCompetitors(referenceUrl, targetMarket, productContext, referenceCity, referenceCountry, idealCustomerProfile); setCategorizedCompetitors(identifiedCompetitors); // Store categorized competitors // Flatten categorized competitors into a single list for existing StepReview component const flatCompetitors: Competitor[] = [ ...(identifiedCompetitors.localCompetitors || []), ...(identifiedCompetitors.nationalCompetitors || []), ...(identifiedCompetitors.internationalCompetitors || []), ]; setCompetitors(flatCompetitors); // Set the flattened list for StepReview setStep(AppStep.REVIEW_LIST); } catch (e) { alert("Failed to find companies."); console.error(e); } finally { setIsLoading(false); } }; const handleRemoveCompetitor = (id: string) => { setCompetitors(prev => prev.filter(c => c.id !== id)); }; const handleAddCompetitor = (name: string) => { setCompetitors(prev => [...prev, { id: generateId(), name }]); }; const runAnalysis = useCallback(async () => { if (!strategy) return; setStep(AppStep.ANALYSIS); setAnalysisResults([]); setProcessingState({ currentCompany: '', progress: 0, total: competitors.length, completed: 0, terminalLogs: ['🚀 Starting Deep Tech Audit session...'] }); const results: AnalysisResult[] = []; const addLog = (msg: string) => { setProcessingState(prev => ({ ...prev, terminalLogs: [...(prev.terminalLogs || []), msg] })); }; for (let i = 0; i < competitors.length; i++) { const comp = competitors[i]; setProcessingState(prev => ({ ...prev, currentCompany: comp.name })); addLog(`> Analyzing ${comp.name} (${i + 1}/${competitors.length})`); try { // Step-by-step logging to make it feel real and informative addLog(` 🔍 Searching official website for ${comp.name}...`); // The actual API call happens here. While waiting, the user sees the search log. const result = await analyzeCompanyWithStrategy(comp.name, strategy, language); if (result.dataSource === "Error") { addLog(` ❌ Error: Could not process ${comp.name}.`); } else { const websiteStatus = result.dataSource === "Digital Trace Audit" ? "Verified" : (result.dataSource || "Unknown"); const revenue = result.revenue || "N/A"; const employees = result.employees || "N/A"; const status = result.status || "Unknown"; const tier = result.tier || "N/A"; addLog(` ✓ Found website: ${websiteStatus}`); addLog(` 📊 Estimated: ${revenue} revenue, ${employees} employees.`); addLog(` 🎯 Status: ${status} | Tier: ${tier}`); addLog(` ✅ Analysis complete for ${comp.name}.`); } results.push(result); } catch (e) { console.error(`Failed to analyze ${comp.name}`); addLog(` ❌ Fatal error analyzing ${comp.name}.`); } setProcessingState(prev => ({ ...prev, completed: i + 1 })); } addLog(`✨ Audit session finished. Generating final report...`); setAnalysisResults(results); setStep(AppStep.REPORT); }, [competitors, language, strategy]); const handleRestart = () => { setCompetitors([]); setAnalysisResults([]); setStrategy(null); setStep(AppStep.INPUT); }; return (
{step === AppStep.INPUT && ( )} {step === AppStep.STRATEGY && strategy && ( )} {step === AppStep.REVIEW_LIST && ( 0} onShowReport={() => setStep(AppStep.REPORT)} /> )} {step === AppStep.ANALYSIS && ( )} {step === AppStep.REPORT && strategy && ( { setSelectedCompanyForOutreach(company); setStep(AppStep.OUTREACH); }} /> )} {step === AppStep.OUTREACH && selectedCompanyForOutreach && ( )}
); }; export default App;