import { Edge, Node } from 'reactflow' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' import { ScrollArea } from '@/components/ui/scroll-area' import { FeatureIdea, IdeaEdgeData } from './types' type FeatureIdeaDebugPanelProps = { nodes: Node[] edges: Edge[] safeIdeas: FeatureIdea[] onClose: () => void } type HandleStats = { leftHandles: Edge[] rightHandles: Edge[] topHandles: Edge[] bottomHandles: Edge[] leftUnique: number rightUnique: number topUnique: number bottomUnique: number nodeEdges: Edge[] } const getHandleStats = (ideaId: string, edges: Edge[]): HandleStats => { const nodeEdges = edges.filter((edge) => edge.source === ideaId || edge.target === ideaId) const leftHandles = edges.filter((edge) => edge.target === ideaId && edge.targetHandle?.startsWith('left')) const rightHandles = edges.filter((edge) => edge.source === ideaId && edge.sourceHandle?.startsWith('right')) const topHandles = edges.filter((edge) => edge.target === ideaId && edge.targetHandle?.startsWith('top')) const bottomHandles = edges.filter((edge) => edge.source === ideaId && edge.sourceHandle?.startsWith('bottom')) return { leftHandles, rightHandles, topHandles, bottomHandles, leftUnique: new Set(leftHandles.map((edge) => edge.targetHandle)).size, rightUnique: new Set(rightHandles.map((edge) => edge.sourceHandle)).size, topUnique: new Set(topHandles.map((edge) => edge.targetHandle)).size, bottomUnique: new Set(bottomHandles.map((edge) => edge.sourceHandle)).size, nodeEdges, } } const DebugSummary = ({ nodes, edges, safeIdeas }: Omit) => (
Total Edges
{edges.length}
Total Nodes
{nodes.length}
Total Ideas
{safeIdeas.length}
) const ConnectionMatrix = ({ safeIdeas, edges }: Pick) => (
Connection Matrix (Handle Occupancy) 1:1 Constraint Active
{safeIdeas.slice(0, 10).map((idea) => { const { nodeEdges, leftHandles, rightHandles, topHandles, bottomHandles, leftUnique, rightUnique, topUnique, bottomUnique } = getHandleStats(idea.id, edges) const hasViolation = leftHandles.length !== leftUnique || rightHandles.length !== rightUnique || topHandles.length !== topUnique || bottomHandles.length !== bottomUnique return (
{hasViolation && ⚠️} {idea.title}
= 1 ? 'bg-green-500/20 text-green-700 dark:text-green-300' : 'bg-muted' }`} > ← {leftHandles.length}/{leftUnique} {leftHandles.length !== leftUnique ? '⚠️' : leftHandles.length > 0 ? '✓' : '○'}
= 1 ? 'bg-green-500/20 text-green-700 dark:text-green-300' : 'bg-muted' }`} > → {rightHandles.length}/{rightUnique} {rightHandles.length !== rightUnique ? '⚠️' : rightHandles.length > 0 ? '✓' : '○'}
= 1 ? 'bg-green-500/20 text-green-700 dark:text-green-300' : 'bg-muted' }`} > ↑ {topHandles.length}/{topUnique} {topHandles.length !== topUnique ? '⚠️' : topHandles.length > 0 ? '✓' : '○'}
= 1 ? 'bg-green-500/20 text-green-700 dark:text-green-300' : 'bg-muted' }`} > ↓ {bottomHandles.length}/{bottomUnique} {bottomHandles.length !== bottomUnique ? '⚠️' : bottomHandles.length > 0 ? '✓' : '○'}
Total: {nodeEdges.length} connection{nodeEdges.length !== 1 ? 's' : ''}, Handles: L{leftUnique}|R{rightUnique}|T {topUnique}|B{bottomUnique}
) })} {safeIdeas.length > 10 && (
... and {safeIdeas.length - 10} more ideas
)}
) const ConstraintStatus = ({ safeIdeas, edges }: Pick) => { const violations: string[] = [] safeIdeas.forEach((idea) => { const { leftHandles, rightHandles, topHandles, bottomHandles, leftUnique, rightUnique, topUnique, bottomUnique } = getHandleStats( idea.id, edges ) if (leftHandles.length !== leftUnique) { violations.push(`${idea.title}: Left side has duplicate handle usage (${leftHandles.length} connections on ${leftUnique} handles)`) } if (rightHandles.length !== rightUnique) { violations.push(`${idea.title}: Right side has duplicate handle usage (${rightHandles.length} connections on ${rightUnique} handles)`) } if (topHandles.length !== topUnique) { violations.push(`${idea.title}: Top side has duplicate handle usage (${topHandles.length} connections on ${topUnique} handles)`) } if (bottomHandles.length !== bottomUnique) { violations.push(`${idea.title}: Bottom side has duplicate handle usage (${bottomHandles.length} connections on ${bottomUnique} handles)`) } }) if (violations.length > 0) { return (
❌ CONSTRAINT VIOLATIONS DETECTED
{violations.map((violation, index) => (
• {violation}
))}
) } return (
✅ All Constraints Satisfied
• Each handle has exactly 1 connection (1:1 mapping) ✓
• New connections automatically remove conflicts ✓
• Spare blank handles always available ✓
• Remapping preserves 1:1 constraint ✓
• Changes persist to database immediately ✓
) } export const FeatureIdeaDebugPanel = ({ nodes, edges, safeIdeas, onClose }: FeatureIdeaDebugPanelProps) => (

🔍 Connection Debug Panel

)