From 7ff326d8980bca8c70fa879dd42a927fed3ba897 Mon Sep 17 00:00:00 2001 From: AndyMik90 Date: Thu, 18 Dec 2025 20:46:31 +0100 Subject: [PATCH] feat: add interactive competitor analysis viewer for roadmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive competitor analysis viewing capabilities: - Create CompetitorAnalysisViewer component with detailed insights display * Shows competitor names, descriptions, and market positions * Displays pain points with severity badges (high/medium/low) * Includes user quotes from reviews/forums * Shows opportunity scores for prioritization * Provides visit links to competitor products - Make Competitor Analysis badge interactive * Click to open detailed viewer modal * Tooltip shows summary (competitor count, pain points) * Visual feedback with hover state - Enhance persona visibility in roadmap header * Make "+N more personas" clickable with dotted underline * Show all secondary personas in tooltip on hover - Fix modal scrolling in CompetitorAnalysisViewer * Add flex layout constraints for proper scrolling * Set max-height with calculation for header space * Add bottom padding to prevent content cutoff This enables users to view detailed competitive insights generated during roadmap creation, including specific pain points identified in competitor products and opportunities to address market gaps. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../components/CompetitorAnalysisViewer.tsx | 154 ++++++++++++++++++ .../src/renderer/components/Roadmap.tsx | 10 ++ .../components/roadmap/RoadmapHeader.tsx | 20 ++- .../src/renderer/components/roadmap/types.ts | 1 + 4 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx 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 {