diff --git a/src/components/FeatureIdeaCloud.tsx b/src/components/FeatureIdeaCloud.tsx index 5094c67..bf13871 100644 --- a/src/components/FeatureIdeaCloud.tsx +++ b/src/components/FeatureIdeaCloud.tsx @@ -691,594 +691,52 @@ export function FeatureIdeaCloud() { return (
- - - + - - - - - - - Debug Connection Status - - - - - - - AI Generate Ideas - - - - - - - Add Group - - - - - - - Add Idea - - - - - -
-

💡 Tip: Double-click ideas to view details

-

📦 Create groups to organize related ideas

-

🔗 Drag from handles on card edges to connect ideas

-

↪️ Drag existing connection ends to remap them

-

⚙️ Click connections to edit or delete them

-
-
- - {debugPanelOpen && ( - - -
-
-

🔍 Connection Debug Panel

- -
- -
-
-
Total Edges
-
{edges.length}
-
-
-
Total Nodes
-
{nodes.length}
-
-
-
Total Ideas
-
{safeIdeas.length}
-
-
- -
-
- Connection Matrix (Handle Occupancy) - 1:1 Constraint Active -
- -
- {safeIdeas.slice(0, 10).map((idea) => { - const nodeEdges = edges.filter(e => e.source === idea.id || e.target === idea.id) - const leftHandles = edges.filter(e => e.target === idea.id && e.targetHandle?.startsWith('left')) - const rightHandles = edges.filter(e => e.source === idea.id && e.sourceHandle?.startsWith('right')) - const topHandles = edges.filter(e => e.target === idea.id && e.targetHandle?.startsWith('top')) - const bottomHandles = edges.filter(e => e.source === idea.id && e.sourceHandle?.startsWith('bottom')) - - const leftUnique = new Set(leftHandles.map(e => e.targetHandle)).size - const rightUnique = new Set(rightHandles.map(e => e.sourceHandle)).size - const topUnique = new Set(topHandles.map(e => e.targetHandle)).size - const bottomUnique = new Set(bottomHandles.map(e => e.sourceHandle)).size - - 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 violations: string[] = [] - safeIdeas.forEach(idea => { - const leftHandles = edges.filter(e => e.target === idea.id && e.targetHandle?.startsWith('left')) - const rightHandles = edges.filter(e => e.source === idea.id && e.sourceHandle?.startsWith('right')) - const topHandles = edges.filter(e => e.target === idea.id && e.targetHandle?.startsWith('top')) - const bottomHandles = edges.filter(e => e.source === idea.id && e.sourceHandle?.startsWith('bottom')) - - const leftUnique = new Set(leftHandles.map(e => e.targetHandle)).size - const rightUnique = new Set(rightHandles.map(e => e.sourceHandle)).size - const topUnique = new Set(topHandles.map(e => e.targetHandle)).size - const bottomUnique = new Set(bottomHandles.map(e => e.sourceHandle)).size - - 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)`) - }) - - return violations.length > 0 ? ( -
-
- ❌ CONSTRAINT VIOLATIONS DETECTED -
-
- {violations.map((v, i) => ( -
• {v}
- ))} -
-
- ) : ( -
-
- ✅ 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 ✓
-
-
- ) - })()} -
-
-
- )} -
- - - - - - {selectedGroup?.label ? 'Edit Group' : 'New Group'} - - - Create a container to organize related ideas - - - - {selectedGroup && ( -
-
- - setSelectedGroup({ ...selectedGroup, label: e.target.value })} - placeholder="e.g., Authentication Features" - /> -
- -
- -
- {GROUP_COLORS.map(color => ( -
-
- -
-

💡 Tips:

-
    -
  • • Groups provide visual organization for related ideas
  • -
  • • Drag ideas into groups or assign them in the idea editor
  • -
  • • Ideas stay within their group boundaries when moved
  • -
-
-
- )} - - -
-
- {selectedGroup && groups?.find(g => g.id === selectedGroup.id) && ( - - )} -
-
- - -
-
-
-
-
- - - - - - {selectedIdea?.title ? 'Edit Idea' : 'New Idea'} - - - Create or modify a feature idea for your app - - - - {selectedIdea && ( -
-
- - setSelectedIdea({ ...selectedIdea, title: e.target.value })} - placeholder="Feature name..." - /> -
- -
- -