diff --git a/src/components/FeatureIdeaCloud.tsx b/src/components/FeatureIdeaCloud.tsx index dc07481..a4e5acc 100644 --- a/src/components/FeatureIdeaCloud.tsx +++ b/src/components/FeatureIdeaCloud.tsx @@ -26,6 +26,7 @@ import { toast } from 'sonner' import { FeatureIdea, IdeaGroup, IdeaEdgeData } from './FeatureIdeaCloud/types' import { SEED_IDEAS, CATEGORIES, PRIORITIES, STATUSES, CONNECTION_STYLE, GROUP_COLORS } from './FeatureIdeaCloud/constants' import { nodeTypes } from './FeatureIdeaCloud/nodes' +import { dispatchConnectionCountUpdate } from './FeatureIdeaCloud/dispatchConnectionCountUpdate' export function FeatureIdeaCloud() { const [ideas, setIdeas] = useKV('feature-ideas', SEED_IDEAS) @@ -114,10 +115,7 @@ export function FeatureIdeaCloud() { bottom: connections.bottom.size, } - const event = new CustomEvent('updateConnectionCounts', { - detail: { nodeId, counts } - }) - window.dispatchEvent(event) + dispatchConnectionCountUpdate(nodeId, counts) }) }, []) diff --git a/src/components/FeatureIdeaCloud/GroupNode.tsx b/src/components/FeatureIdeaCloud/GroupNode.tsx new file mode 100644 index 0000000..61a1968 --- /dev/null +++ b/src/components/FeatureIdeaCloud/GroupNode.tsx @@ -0,0 +1,44 @@ +import { NodeProps } from 'reactflow' +import { Button } from '@/components/ui/button' +import { DotsThree } from '@phosphor-icons/react' +import { IdeaGroup } from './types' +import { GROUP_COLORS } from './constants' +import { dispatchEditGroup } from './dispatchEditGroup' + +export function GroupNode({ data, selected }: NodeProps) { + const colorScheme = GROUP_COLORS.find(c => c.value === data.color) || GROUP_COLORS[0] + + return ( +
+
+ {data.label} +
+ +
+ ) +} diff --git a/src/components/FeatureIdeaCloud/IdeaNode.tsx b/src/components/FeatureIdeaCloud/IdeaNode.tsx new file mode 100644 index 0000000..1b1ed52 --- /dev/null +++ b/src/components/FeatureIdeaCloud/IdeaNode.tsx @@ -0,0 +1,72 @@ +import { useState, useEffect } from 'react' +import { NodeProps, Position } from 'reactflow' +import { Button } from '@/components/ui/button' +import { Card } from '@/components/ui/card' +import { Badge } from '@/components/ui/badge' +import { DotsThree } from '@phosphor-icons/react' +import { FeatureIdea } from './types' +import { PRIORITY_COLORS, STATUS_COLORS } from './constants' +import { generateHandles } from './generateHandles' +import { dispatchEditIdea } from './dispatchEditIdea' + +export function IdeaNode({ data, selected, id }: NodeProps & { id: string }) { + const [connectionCounts, setConnectionCounts] = useState>({ + left: 0, + right: 0, + top: 0, + bottom: 0, + }) + + useEffect(() => { + const updateConnectionCounts = (event: CustomEvent) => { + const { nodeId, counts } = event.detail + if (nodeId === id) { + setConnectionCounts(counts) + } + } + + window.addEventListener('updateConnectionCounts' as any, updateConnectionCounts as EventListener) + return () => { + window.removeEventListener('updateConnectionCounts' as any, updateConnectionCounts as EventListener) + } + }, [id]) + + return ( +
+ {generateHandles({ position: Position.Left, type: 'target', side: 'left', count: connectionCounts.left })} + {generateHandles({ position: Position.Right, type: 'source', side: 'right', count: connectionCounts.right })} + {generateHandles({ position: Position.Top, type: 'target', side: 'top', count: connectionCounts.top })} + {generateHandles({ position: Position.Bottom, type: 'source', side: 'bottom', count: connectionCounts.bottom })} + + +
+
+

{data.title}

+ +
+

+ {data.description} +

+
+ + {data.category} + + + {data.status} + +
+
+
+
+ ) +} diff --git a/src/components/FeatureIdeaCloud/dispatchConnectionCountUpdate.ts b/src/components/FeatureIdeaCloud/dispatchConnectionCountUpdate.ts new file mode 100644 index 0000000..3d7f85c --- /dev/null +++ b/src/components/FeatureIdeaCloud/dispatchConnectionCountUpdate.ts @@ -0,0 +1,6 @@ +export function dispatchConnectionCountUpdate(nodeId: string, counts: Record) { + const event = new CustomEvent('updateConnectionCounts', { + detail: { nodeId, counts } + }) + window.dispatchEvent(event) +} diff --git a/src/components/FeatureIdeaCloud/dispatchEditGroup.ts b/src/components/FeatureIdeaCloud/dispatchEditGroup.ts new file mode 100644 index 0000000..3af9800 --- /dev/null +++ b/src/components/FeatureIdeaCloud/dispatchEditGroup.ts @@ -0,0 +1,6 @@ +import { IdeaGroup } from './types' + +export function dispatchEditGroup(group: IdeaGroup) { + const event = new CustomEvent('editGroup', { detail: group }) + window.dispatchEvent(event) +} diff --git a/src/components/FeatureIdeaCloud/dispatchEditIdea.ts b/src/components/FeatureIdeaCloud/dispatchEditIdea.ts new file mode 100644 index 0000000..2a7bfdd --- /dev/null +++ b/src/components/FeatureIdeaCloud/dispatchEditIdea.ts @@ -0,0 +1,6 @@ +import { FeatureIdea } from './types' + +export function dispatchEditIdea(idea: FeatureIdea) { + const event = new CustomEvent('editIdea', { detail: idea }) + window.dispatchEvent(event) +} diff --git a/src/components/FeatureIdeaCloud/utils.tsx b/src/components/FeatureIdeaCloud/generateHandles.tsx similarity index 69% rename from src/components/FeatureIdeaCloud/utils.tsx rename to src/components/FeatureIdeaCloud/generateHandles.tsx index 1a08ee7..01411c6 100644 --- a/src/components/FeatureIdeaCloud/utils.tsx +++ b/src/components/FeatureIdeaCloud/generateHandles.tsx @@ -11,7 +11,7 @@ interface GenerateHandlesProps { export function generateHandles({ position, type, side, count }: GenerateHandlesProps): ReactElement[] { const totalHandles = Math.max(2, count + 1) const handles: ReactElement[] = [] - + for (let i = 0; i < totalHandles; i++) { const handleId = `${side}-${i}` const isVertical = position === Position.Top || position === Position.Bottom @@ -20,7 +20,7 @@ export function generateHandles({ position, type, side, count }: GenerateHandles const positionStyle = isVertical ? { left: `${leftPercent}%` } : { top: `${topPercent}%` } - + const element = ( ) { - const event = new CustomEvent('updateConnectionCounts', { - detail: { nodeId, counts } - }) - window.dispatchEvent(event) -} - -export function dispatchEditIdea(idea: any) { - const event = new CustomEvent('editIdea', { detail: idea }) - window.dispatchEvent(event) -} - -export function dispatchEditGroup(group: any) { - const event = new CustomEvent('editGroup', { detail: group }) - window.dispatchEvent(event) -} diff --git a/src/components/FeatureIdeaCloud/nodes.tsx b/src/components/FeatureIdeaCloud/nodes.tsx index b1a7b88..604fd1e 100644 --- a/src/components/FeatureIdeaCloud/nodes.tsx +++ b/src/components/FeatureIdeaCloud/nodes.tsx @@ -1,143 +1,5 @@ -import { useState, useEffect, ReactElement } from 'react' -import { NodeProps, Handle, Position } from 'reactflow' -import { Button } from '@/components/ui/button' -import { Card } from '@/components/ui/card' -import { Badge } from '@/components/ui/badge' -import { DotsThree } from '@phosphor-icons/react' -import { FeatureIdea, IdeaGroup } from './types' -import { PRIORITY_COLORS, STATUS_COLORS, GROUP_COLORS } from './constants' - -export function GroupNode({ data, selected }: NodeProps) { - const colorScheme = GROUP_COLORS.find(c => c.value === data.color) || GROUP_COLORS[0] - - return ( -
-
- {data.label} -
- -
- ) -} - -export function IdeaNode({ data, selected, id }: NodeProps & { id: string }) { - const [connectionCounts, setConnectionCounts] = useState>({ - left: 0, - right: 0, - top: 0, - bottom: 0, - }) - - useEffect(() => { - const updateConnectionCounts = (event: CustomEvent) => { - const { nodeId, counts } = event.detail - if (nodeId === id) { - setConnectionCounts(counts) - } - } - - window.addEventListener('updateConnectionCounts' as any, updateConnectionCounts as EventListener) - return () => { - window.removeEventListener('updateConnectionCounts' as any, updateConnectionCounts as EventListener) - } - }, [id]) - - const generateHandles = (position: Position, type: 'source' | 'target', side: string) => { - const count = connectionCounts[side] || 0 - const totalHandles = Math.max(2, count + 1) - const handles: ReactElement[] = [] - - for (let i = 0; i < totalHandles; i++) { - const handleId = `${side}-${i}` - const isVertical = position === Position.Top || position === Position.Bottom - const positionStyle = isVertical - ? { left: `${((i + 1) / (totalHandles + 1)) * 100}%` } - : { top: `${((i + 1) / (totalHandles + 1)) * 100}%` } - - handles.push( - - ) - } - - return handles - } - - return ( -
- {generateHandles(Position.Left, 'target', 'left')} - {generateHandles(Position.Right, 'source', 'right')} - {generateHandles(Position.Top, 'target', 'top')} - {generateHandles(Position.Bottom, 'source', 'bottom')} - - -
-
-

{data.title}

- -
-

- {data.description} -

-
- - {data.category} - - - {data.status} - -
-
-
-
- ) -} +import { GroupNode } from './GroupNode' +import { IdeaNode } from './IdeaNode' export const nodeTypes = { ideaNode: IdeaNode, diff --git a/src/components/FeatureIdeaCloud/utils.ts b/src/components/FeatureIdeaCloud/utils.ts deleted file mode 100644 index b096f6a..0000000 --- a/src/components/FeatureIdeaCloud/utils.ts +++ /dev/null @@ -1,16 +0,0 @@ -export function dispatchConnectionCountUpdate(nodeId: string, counts: Record) { - const event = new CustomEvent('updateConnectionCounts', { - detail: { nodeId, counts } - }) - window.dispatchEvent(event) -} - -export function dispatchEditIdea(idea: any) { - const event = new CustomEvent('editIdea', { detail: idea }) - window.dispatchEvent(event) -} - -export function dispatchEditGroup(group: any) { - const event = new CustomEvent('editGroup', { detail: group }) - window.dispatchEvent(event) -}