diff --git a/auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx b/auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx new file mode 100644 index 00000000..f8f900c6 --- /dev/null +++ b/auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx @@ -0,0 +1,154 @@ +import { TrendingUp, ExternalLink, AlertCircle } from 'lucide-react'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, +} from './ui/dialog'; +import { Badge } from './ui/badge'; +import { ScrollArea } from './ui/scroll-area'; +import type { CompetitorAnalysis } from '../../shared/types'; + +interface CompetitorAnalysisViewerProps { + analysis: CompetitorAnalysis | null; + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function CompetitorAnalysisViewer({ + analysis, + open, + onOpenChange, +}: CompetitorAnalysisViewerProps) { + if (!analysis) return null; + + return ( + + + + + + Competitor Analysis Results + + + Analyzed {analysis.competitors.length} competitors to identify market gaps and opportunities + + + + +
+ {analysis.competitors.map((competitor) => ( +
+ {/* Competitor Header */} +
+
+
+

{competitor.name}

+ {competitor.marketPosition && ( + + {competitor.marketPosition} + + )} +
+ {competitor.description && ( +

+ {competitor.description} +

+ )} +
+ {competitor.url && ( + + + Visit + + )} +
+ + {/* Pain Points */} +
+

+ + Identified Pain Points ({competitor.painPoints.length}) +

+
+ {competitor.painPoints.length === 0 ? ( +

+ No pain points identified +

+ ) : ( + competitor.painPoints.map((painPoint) => ( +
+
+ + {painPoint.severity} + +
+

+ {painPoint.description} +

+ {painPoint.userQuotes && painPoint.userQuotes.length > 0 && ( +
+ {painPoint.userQuotes.map((quote, idx) => ( +

+ "{quote}" +

+ ))} +
+ )} + {painPoint.opportunityScore !== undefined && ( +
+ + Opportunity Score:{' '} + + {painPoint.opportunityScore}/10 + + +
+ )} +
+
+
+ )) + )} +
+
+
+ ))} + + {/* Summary */} + {analysis.summary && ( +
+

Market Summary

+

{analysis.summary}

+
+ )} +
+
+
+
+ ); +} diff --git a/auto-claude-ui/src/renderer/components/Roadmap.tsx b/auto-claude-ui/src/renderer/components/Roadmap.tsx index 0fd91928..e4f65d61 100644 --- a/auto-claude-ui/src/renderer/components/Roadmap.tsx +++ b/auto-claude-ui/src/renderer/components/Roadmap.tsx @@ -1,6 +1,7 @@ import { useState } from 'react'; import { RoadmapGenerationProgress } from './RoadmapGenerationProgress'; import { CompetitorAnalysisDialog } from './CompetitorAnalysisDialog'; +import { CompetitorAnalysisViewer } from './CompetitorAnalysisViewer'; import { AddFeatureDialog } from './AddFeatureDialog'; import { RoadmapHeader } from './roadmap/RoadmapHeader'; import { RoadmapEmptyState } from './roadmap/RoadmapEmptyState'; @@ -16,6 +17,7 @@ export function Roadmap({ projectId, onGoToTask }: RoadmapProps) { const [selectedFeature, setSelectedFeature] = useState(null); const [activeTab, setActiveTab] = useState('phases'); const [showAddFeatureDialog, setShowAddFeatureDialog] = useState(false); + const [showCompetitorViewer, setShowCompetitorViewer] = useState(false); // Custom hooks const { roadmap, competitorAnalysis, generationStatus } = useRoadmapData(projectId); @@ -78,6 +80,7 @@ export function Roadmap({ projectId, onGoToTask }: RoadmapProps) { competitorAnalysis={competitorAnalysis} onAddFeature={() => setShowAddFeatureDialog(true)} onRefresh={handleRefresh} + onViewCompetitorAnalysis={() => setShowCompetitorViewer(true)} /> {/* Content */} @@ -111,6 +114,13 @@ export function Roadmap({ projectId, onGoToTask }: RoadmapProps) { onDecline={handleCompetitorDialogDecline} /> + {/* Competitor Analysis Viewer */} + + {/* Add Feature Dialog */} - + Competitor Analysis
-
Analyzed {competitorAnalysis.competitors.length} competitors:
- {competitorAnalysis.competitors.map((comp) => ( -
-
• {comp.name}
-
{comp.painPoints.length} pain points identified
-
- ))} +
Click to view detailed analysis
+
+ Analyzed {competitorAnalysis.competitors.length} competitors with {' '} + {competitorAnalysis.competitors.reduce((sum, c) => sum + c.painPoints.length, 0)} pain points identified +
diff --git a/auto-claude-ui/src/renderer/components/roadmap/types.ts b/auto-claude-ui/src/renderer/components/roadmap/types.ts index db1d85c7..40db7c0b 100644 --- a/auto-claude-ui/src/renderer/components/roadmap/types.ts +++ b/auto-claude-ui/src/renderer/components/roadmap/types.ts @@ -35,6 +35,7 @@ export interface RoadmapHeaderProps { competitorAnalysis: CompetitorAnalysis | null; onAddFeature: () => void; onRefresh: () => void; + onViewCompetitorAnalysis?: () => void; } export interface RoadmapEmptyStateProps {