"use client"; import { motion, AnimatePresence } from "framer-motion"; import { Globe, FileText, Code, Shield, // Search, // Not used in current implementation Zap, Database, // Lock, // Not used in current implementation CheckCircle2, XCircle, Loader2, AlertCircle, Bot, Sparkles, FileCode, Network, Info, Eye } from "lucide-react"; import { useEffect, useState } from "react"; import ScoreChart from "./ScoreChart"; import RadarChart from "./RadarChart"; import MetricBars from "./MetricBars"; interface ControlPanelProps { isAnalyzing: boolean; showResults: boolean; url: string; analysisData?: any; onReset: () => void; } interface CheckItem { id: string; label: string; description: string; icon: any; status: 'pending' | 'checking' | 'pass' | 'fail' | 'warning'; score?: number; details?: string; recommendation?: string; actionItems?: string[]; tooltip?: string; } export default function ControlPanel({ isAnalyzing, showResults, url, analysisData, onReset, }: ControlPanelProps) { const [showAIAnalysis, setShowAIAnalysis] = useState(false); // Reserved for AI analysis feature const [aiInsights, setAiInsights] = useState([]); const [isAnalyzingAI, setIsAnalyzingAI] = useState(false); const [combinedChecks, setCombinedChecks] = useState([]); const [checks, setChecks] = useState([ { id: 'heading-structure', label: 'Heading Hierarchy', description: 'H1-H6 structure', icon: FileText, status: 'pending', }, { id: 'readability', label: 'Readability', description: 'Content clarity', icon: Globe, status: 'pending', }, { id: 'meta-tags', label: 'Metadata Quality', description: 'Title, desc, author', icon: FileCode, status: 'pending', }, { id: 'semantic-html', label: 'Semantic HTML', description: 'Proper HTML5 tags', icon: Code, status: 'pending', }, { id: 'accessibility', label: 'Accessibility', description: 'Alt text & ARIA', icon: Eye, status: 'pending', }, { id: 'llms-txt', label: 'LLMs.txt', description: 'AI permissions', icon: Bot, status: 'pending', }, { id: 'robots-txt', label: 'Robots.txt', description: 'Crawler rules', icon: Shield, status: 'pending', }, { id: 'sitemap', label: 'Sitemap', description: 'Site structure', icon: Network, status: 'pending', }, ]); const [overallScore, setOverallScore] = useState(0); const [currentCheckIndex, setCurrentCheckIndex] = useState(-1); const [selectedCheck, setSelectedCheck] = useState(null); const [hoveredCheck, setHoveredCheck] = useState(null); const [enhancedScore, setEnhancedScore] = useState(0); const [viewMode, setViewMode] = useState<'grid' | 'chart' | 'bars'>('grid'); useEffect(() => { if (analysisData && analysisData.checks && showResults) { // Use real data from API const mappedChecks = analysisData.checks.map((check: any) => ({ ...check, icon: checks.find(c => c.id === check.id)?.icon || FileText, description: check.details || checks.find(c => c.id === check.id)?.description, })); setChecks(mappedChecks); setCombinedChecks(mappedChecks); // Initialize with basic checks setOverallScore(analysisData.overallScore || 0); setCurrentCheckIndex(-1); // If AI analysis should auto-start, handle the promise if (analysisData.autoStartAI && analysisData.aiAnalysisPromise) { console.log('Auto-starting AI analysis with promise'); setIsAnalyzingAI(true); setShowAIAnalysis(true); // Add placeholder AI tiles immediately with actual titles const placeholderAIChecks = [ { id: 'ai-loading-0', label: 'Content Quality for AI', description: 'Analyzing content signal ratio...', icon: Sparkles, status: 'checking' as const, score: 0, isAI: true, isLoading: true }, { id: 'ai-loading-1', label: 'Information Architecture', description: 'Evaluating page structure...', icon: Bot, status: 'checking' as const, score: 0, isAI: true, isLoading: true }, { id: 'ai-loading-2', label: 'Crawlability Patterns', description: 'Checking JavaScript usage...', icon: Database, status: 'checking' as const, score: 0, isAI: true, isLoading: true }, { id: 'ai-loading-3', label: 'AI Training Value', description: 'Assessing training potential...', icon: Network, status: 'checking' as const, score: 0, isAI: true, isLoading: true }, { id: 'ai-loading-4', label: 'Knowledge Extraction', description: 'Analyzing entity definitions...', icon: FileCode, status: 'checking' as const, score: 0, isAI: true, isLoading: true }, { id: 'ai-loading-5', label: 'Template Quality', description: 'Reviewing semantic structure...', icon: Shield, status: 'checking' as const, score: 0, isAI: true, isLoading: true }, { id: 'ai-loading-6', label: 'Content Depth', description: 'Measuring content richness...', icon: Zap, status: 'checking' as const, score: 0, isAI: true, isLoading: true }, { id: 'ai-loading-7', label: 'Machine Readability', description: 'Testing extraction reliability...', icon: Globe, status: 'checking' as const, score: 0, isAI: true, isLoading: true } ]; // Add loading AI tiles with staggered animation placeholderAIChecks.forEach((check, idx) => { setTimeout(() => { setCombinedChecks(prev => [...prev, check]); }, 100 * (idx + 1)); }); // Handle the AI analysis promise analysisData.aiAnalysisPromise .then(async (aiResponse: any) => { if (aiResponse) { const data = await aiResponse.json(); if (data.success && data.insights) { // Convert AI insights to CheckItem format const aiChecks: CheckItem[] = data.insights.map((insight: any, idx: number) => ({ ...insight, icon: [Sparkles, Bot, Database, Network, FileCode, Shield, Zap, Globe][idx % 8], description: insight.details?.substring(0, 60) + '...' || 'AI Analysis', isAI: true, })); setAiInsights(aiChecks); // Replace loading tiles with real AI tiles setCombinedChecks(prev => { // Remove loading tiles const withoutLoading = prev.filter(c => !(c as any).isLoading); // Add real AI tiles return [...withoutLoading, ...aiChecks]; }); // Calculate enhanced score if (data.insights.length > 0) { const aiScores = data.insights.map((i: any) => i.score || 0); const avgAiScore = aiScores.reduce((a: number, b: number) => a + b, 0) / aiScores.length; const combinedScore = Math.round((overallScore * 0.6) + (avgAiScore * 0.4)); setEnhancedScore(combinedScore); } } } }) .catch((error: any) => { console.error('AI analysis error:', error); // Remove loading tiles on error setCombinedChecks(prev => prev.filter(c => !(c as any).isLoading)); }) .finally(() => { setIsAnalyzingAI(false); }); } } else if (isAnalyzing) { // Reset all checks when starting analysis const resetChecks = checks.map(check => ({ ...check, status: 'pending' as const })); setChecks(resetChecks); setCombinedChecks(resetChecks); // Reset combined checks too setCurrentCheckIndex(0); setOverallScore(0); // Visual animation while waiting for real results const checkInterval = setInterval(() => { setCurrentCheckIndex(prev => { if (prev >= checks.length - 1) { clearInterval(checkInterval); return prev; } return prev + 1; }); }, 200); return () => clearInterval(checkInterval); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isAnalyzing, showResults, analysisData]); useEffect(() => { if (currentCheckIndex >= 0 && currentCheckIndex < checks.length && isAnalyzing) { // Mark current as checking during animation setChecks(prev => prev.map((check, index) => { if (index === currentCheckIndex) { return { ...check, status: 'checking' }; } if (index < currentCheckIndex) { return { ...check, status: 'checking' }; } return check; })); // Update combinedChecks to show the animation setCombinedChecks(prev => prev.map((check, index) => { if (index === currentCheckIndex) { return { ...check, status: 'checking' }; } if (index < currentCheckIndex) { return { ...check, status: 'checking' }; } return check; })); } }, [currentCheckIndex, checks.length, isAnalyzing]); const getStatusIcon = (status: CheckItem['status']) => { switch (status) { case 'checking': return ; case 'pass': return ; case 'fail': return ; case 'warning': return ; default: return
; } }; // Utility function available but not used in current render const getScoreColor = (score: number) => { if (score >= 80) return "text-accent-black"; if (score >= 60) return "text-accent-black"; return "text-accent-black"; }; return ( {/* Header */}

AI Readiness Analysis

Single-page snapshot of {url}

{showResults && ( <> {/* View Mode Toggle - Moved above score */} 0 ? enhancedScore : overallScore} enhanced={enhancedScore > 0} size={180} /> )}
{/* Conditional rendering based on view mode */} {viewMode === 'grid' && (
{combinedChecks.map((check, index) => { const isActive = index === currentCheckIndex; return ( { if (check.status !== 'pending' && check.status !== 'checking') { setSelectedCheck(selectedCheck === check.id ? null : check.id); } }} onMouseEnter={() => setHoveredCheck(check.id)} onMouseLeave={() => setHoveredCheck(null)} >
{getStatusIcon(check.status)}

{check.label} {check.tooltip && !aiInsights.some(ai => ai.id === check.id) && (
{hoveredCheck === check.id && ( {check.tooltip}
)}
)}

{check.description}

{check.status !== 'pending' && check.status !== 'checking' && ( <>
Click for details )}
{/* Expanded Details */} {selectedCheck === check.id && check.details && (
Status
{check.details}
Recommendation
{check.recommendation}
{check.actionItems && check.actionItems.length > 0 && (
    {check.actionItems.map((item: string, i: number) => (
  • {item}
  • ))}
)}
)}
); })}
)} {/* Radar Chart View */} {viewMode === 'chart' && showResults && (
{/* Basic Analysis Chart */}

Basic Analysis

check.status !== 'pending' && check.status !== 'checking') .slice(0, 8) .map(check => ({ label: check.label.length > 12 ? check.label.substring(0, 12) + '...' : check.label, score: check.score || 0 }))} size={350} />
{overallScore}%
Overall Score
{/* VS Indicator */} {aiInsights.length > 0 && (
VS
)} {/* AI Analysis Chart - Only show if AI insights exist */} {aiInsights.length > 0 && (

AI Enhanced Analysis

check.status !== 'pending' && check.status !== 'checking') .slice(0, 8) .map(check => ({ label: check.label.length > 12 ? check.label.substring(0, 12) + '...' : check.label, score: check.score || 0 }))} size={350} />
{Math.round(aiInsights.reduce((sum, check) => sum + (check.score || 0), 0) / aiInsights.length)}%
AI Score
)}
{/* Comparison Summary */} {aiInsights.length > 0 && (
AI analysis found {aiInsights.filter(i => i.score && i.score < 50).length} additional areas for improvement
)}
)} {/* Bar Chart View */} {viewMode === 'bars' && showResults && ( check.status !== 'pending' && check.status !== 'checking') .map(check => ({ label: check.label, score: check.score || 0, status: check.status as 'pass' | 'warning' | 'fail', category: (check as any).isAI ? 'ai' : ['robots-txt', 'sitemap', 'llms-txt'].includes(check.id) ? 'domain' : 'page', details: check.details, recommendation: check.recommendation, actionItems: check.actionItems }))} /> )} {/* Action Buttons */} {showResults && ( {true && ( )} )}
); }