import React, { useState, useEffect } from 'react'; import { Box, Grid, Paper, Typography, Button, TextField, Card, CardContent, Chip, Divider, Alert, CircularProgress, List, ListItem, ListItemText, ListItemIcon } from '@mui/material'; import { Search as SearchIcon, Add as AddIcon, Warning as WarningIcon, CheckCircle as CheckCircleIcon, TrendingUp as TrendingUpIcon, Assessment as AssessmentIcon } from '@mui/icons-material'; import { useContentPlanningStore } from '../../../stores/contentPlanningStore'; import { contentPlanningApi } from '../../../services/contentPlanningApi'; const RefineAnalysisTab: React.FC = () => { const { gapAnalyses, loading, error, loadGapAnalyses, analyzeContentGaps, updateGapAnalyses } = useContentPlanningStore(); const [analysisForm, setAnalysisForm] = useState({ website_url: '', competitors: [] as string[], keywords: [] as string[] }); const [newCompetitor, setNewCompetitor] = useState(''); const [newKeyword, setNewKeyword] = useState(''); const [dataLoading, setDataLoading] = useState(false); useEffect(() => { loadGapAnalysisData(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const loadGapAnalysisData = async () => { try { setDataLoading(true); const response = await contentPlanningApi.getGapAnalysesSafe(); console.log('Gap Analysis Response:', response); // Transform the backend response to match frontend expectations if (response && response.gap_analyses) { const transformedAnalyses = response.gap_analyses.map((analysis: any, index: number) => ({ id: analysis.id || `analysis_${index}`, website_url: analysis.website_url || 'example.com', competitors: analysis.competitors || [], keywords: analysis.keywords || [], gaps: analysis.gaps || [], recommendations: analysis.recommendations || [], created_at: analysis.created_at || new Date().toISOString() })); console.log('Transformed Analyses:', transformedAnalyses); // Update the store with transformed data updateGapAnalyses(transformedAnalyses); } else { console.log('No gap analyses found in response'); updateGapAnalyses([]); } } catch (error) { console.error('Error loading gap analysis data:', error); updateGapAnalyses([]); } finally { setDataLoading(false); } }; const handleAddCompetitor = () => { if (newCompetitor.trim() && !analysisForm.competitors.includes(newCompetitor.trim())) { setAnalysisForm(prev => ({ ...prev, competitors: [...prev.competitors, newCompetitor.trim()] })); setNewCompetitor(''); } }; const handleRemoveCompetitor = (competitorToRemove: string) => { setAnalysisForm(prev => ({ ...prev, competitors: prev.competitors.filter(comp => comp !== competitorToRemove) })); }; const handleAddKeyword = () => { if (newKeyword.trim() && !analysisForm.keywords.includes(newKeyword.trim())) { setAnalysisForm(prev => ({ ...prev, keywords: [...prev.keywords, newKeyword.trim()] })); setNewKeyword(''); } }; const handleRemoveKeyword = (keywordToRemove: string) => { setAnalysisForm(prev => ({ ...prev, keywords: prev.keywords.filter(keyword => keyword !== keywordToRemove) })); }; const handleRunAnalysis = async () => { if (!analysisForm.website_url) { return; } try { setDataLoading(true); await analyzeContentGaps({ website_url: analysisForm.website_url, competitors: analysisForm.competitors, keywords: analysisForm.keywords }); // Reload data after analysis await loadGapAnalyses(); // Reset form setAnalysisForm({ website_url: '', competitors: [], keywords: [] }); } catch (error) { console.error('Error running gap analysis:', error); } finally { setDataLoading(false); } }; // Ensure gapAnalyses is always an array and transform the data structure const safeGapAnalyses = Array.isArray(gapAnalyses) ? gapAnalyses : []; // Transform backend data structure to frontend expected structure const transformedGapAnalyses = safeGapAnalyses.map((analysis, index) => { // Handle the actual backend structure: { recommendations: [...] } const recommendations = analysis.recommendations || []; return { id: analysis.id || `analysis-${index}`, website_url: analysis.website_url || 'Unknown Website', competitors: analysis.competitors || [], keywords: analysis.keywords || [], recommendations: recommendations, created_at: analysis.created_at || new Date().toISOString(), // Extract gaps from recommendations if available gaps: recommendations.length > 0 ? recommendations.filter((rec: any) => rec.type === 'gap').map((rec: any) => rec.title || rec.description || 'Content gap identified') : [] }; }); return ( Refine Analysis {error && ( {error} )} {/* Analysis Setup */} Analysis Setup setAnalysisForm(prev => ({ ...prev, website_url: e.target.value }))} placeholder="https://example.com" sx={{ mb: 2 }} /> Competitors setNewCompetitor(e.target.value)} placeholder="competitor.com" onKeyPress={(e) => e.key === 'Enter' && handleAddCompetitor()} /> {analysisForm.competitors.map((competitor, index) => ( handleRemoveCompetitor(competitor)} color="primary" variant="outlined" /> ))} Keywords setNewKeyword(e.target.value)} placeholder="target keyword" onKeyPress={(e) => e.key === 'Enter' && handleAddKeyword()} /> {analysisForm.keywords.map((keyword, index) => ( handleRemoveKeyword(keyword)} color="secondary" variant="outlined" /> ))} {/* Content Gaps */} Content Gaps {dataLoading ? ( ) : transformedGapAnalyses.length === 0 ? ( No previous analyses found. Run your first analysis to see results here. ) : ( {transformedGapAnalyses.map((analysis) => ( {analysis.website_url} {new Date(analysis.created_at).toLocaleDateString()} ))} )} {/* Detailed Analysis Results */} {transformedGapAnalyses.length > 0 && ( Detailed Analysis Results {transformedGapAnalyses.map((analysis, index) => ( Analysis for {analysis.website_url} {analysis.gaps && analysis.gaps.length > 0 && ( Identified Content Gaps: {analysis.gaps.map((gap, gapIndex) => ( ))} )} {analysis.recommendations && analysis.recommendations.length > 0 && ( Recommendations: {analysis.recommendations.map((rec, recIndex) => ( ))} )} ))} )} ); }; export default RefineAnalysisTab;